Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +14 -0
- README.md +54 -0
- advanced-security-platform.html +1265 -0
- ar-controller.js +996 -0
- gesture-controller.js +1002 -0
- holographic-security-center.html +534 -0
- holographic-security-command.js +0 -0
- imgs/browser_security_0.png +0 -0
- imgs/browser_security_6.png +3 -0
- imgs/browser_security_8.png +3 -0
- imgs/csp_code_3.png +3 -0
- imgs/csp_code_7.jpg +3 -0
- imgs/csp_code_8.axd +3 -0
- imgs/cyber_threats_0.png +0 -0
- imgs/cyber_threats_2.jpg +3 -0
- imgs/cyber_threats_9.jpg +0 -0
- imgs/data_protection_1.jpeg +3 -0
- imgs/data_protection_3.png +0 -0
- imgs/data_protection_5.jpg +3 -0
- imgs/image_meta.json +452 -0
- imgs/security_shield_1.axd +3 -0
- imgs/security_shield_2.png +0 -0
- imgs/security_shield_4.webp +0 -0
- imgs/ssl_security_5.png +3 -0
- imgs/ssl_security_7.jpg +0 -0
- imgs/ssl_security_8.webp +0 -0
- imgs/trusted_types_0.png +3 -0
- imgs/trusted_types_3.png +0 -0
- imgs/trusted_types_7.jpg +3 -0
- imgs/waf_protection_0.png +0 -0
- imgs/waf_protection_5.png +0 -0
- imgs/waf_protection_7.jpg +0 -0
- imgs/web_security_0.png +3 -0
- imgs/web_security_4.jpg +0 -0
- imgs/web_security_8.png +0 -0
- imgs/xss_prevention_3.png +3 -0
- imgs/xss_prevention_6.jpg +0 -0
- imgs/xss_prevention_9.png +0 -0
- index.html +878 -0
- js/3d-interactive-interface.js +1089 -0
- js/advanced-vulnerability-detector.js +1344 -0
- js/ai-behavioral-analyzer.js +734 -0
- js/ai-threat-analyzer.js +694 -0
- js/components.js +787 -0
- js/main.js +503 -0
- js/real-time-monitor.js +719 -0
- js/security-dashboard.js +1158 -0
- js/security-training.js +1110 -0
- js/service-worker-manager.js +820 -0
- js/smart-policy-generator.js +1036 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,17 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
imgs/browser_security_6.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
imgs/browser_security_8.png filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
imgs/csp_code_3.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
imgs/csp_code_7.jpg filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
imgs/csp_code_8.axd filter=lfs diff=lfs merge=lfs -text
|
| 41 |
+
imgs/cyber_threats_2.jpg filter=lfs diff=lfs merge=lfs -text
|
| 42 |
+
imgs/data_protection_1.jpeg filter=lfs diff=lfs merge=lfs -text
|
| 43 |
+
imgs/data_protection_5.jpg filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
imgs/security_shield_1.axd filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
imgs/ssl_security_5.png filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
imgs/trusted_types_0.png filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
imgs/trusted_types_7.jpg filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
imgs/web_security_0.png filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
imgs/xss_prevention_3.png filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🛡️ مشروع سياسة أمان المحتوى (CSP) - الإصدار المطور 2026
|
| 2 |
+
|
| 3 |
+
## 🌟 نظرة عامة | Overview
|
| 4 |
+
هذا المشروع هو المرجع العربي الأول والشامل لتطبيق **سياسة أمان المحتوى (Content Security Policy)**. يهدف إلى تمكين المطورين من حماية تطبيقات الويب الخاصة بهم ضد هجمات XSS و Clickjacking وغيرها من الثغرات الأمنية باستخدام أحدث المعايير التقنية.
|
| 5 |
+
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
## 🚀 الميزات الجديدة | New Features
|
| 9 |
+
|
| 10 |
+
- **CSP Level 3 & 4**: دعم كامل لأحدث توجيهات الأمان.
|
| 11 |
+
- **Trusted Types**: حماية متقدمة ضد ثغرات DOM-based XSS.
|
| 12 |
+
- **Interactive Tools**: أدوات تفاعلية مدمجة لاختبار وتوليد سياسات الأمان.
|
| 13 |
+
- **Modern UI**: واجهة مستخدم عصرية مبنية باستخدام تقنيات الويب الحديثة.
|
| 14 |
+
- **Dark Mode Support**: دعم الوضع الليلي التلقائي.
|
| 15 |
+
|
| 16 |
+
---
|
| 17 |
+
|
| 18 |
+
## 🛠️ الأدوات المضمنة | Included Tools
|
| 19 |
+
|
| 20 |
+
1. **CSP Builder**: منشئ سياسات تفاعلي سهل الاستخدام.
|
| 21 |
+
2. **Security Scanner**: فحص سريع لرؤوس الأمان (Security Headers).
|
| 22 |
+
3. **Code Analyzer**: تحليل الكود المصدري لاكتشاف الممارسات غير الآمنة.
|
| 23 |
+
|
| 24 |
+
---
|
| 25 |
+
|
| 26 |
+
## 📚 كيف تبدأ | How to Start
|
| 27 |
+
|
| 28 |
+
### التشغيل المحلي
|
| 29 |
+
ببساطة قم بفتح ملف `index.html` في متصفحك، أو استخدم خادم محلي:
|
| 30 |
+
|
| 31 |
+
```bash
|
| 32 |
+
# باستخدام Python
|
| 33 |
+
python3 -m http.server 8000
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
---
|
| 37 |
+
|
| 38 |
+
## 📂 هيكل المشروع | Project Structure
|
| 39 |
+
|
| 40 |
+
- `/js`: يحتوي على المتحكمات (Controllers) للميزات التفاعلية.
|
| 41 |
+
- `/styles`: ملفات التنسيق الحديثة والمتجاوبة.
|
| 42 |
+
- `/imgs`: الرسوم التوضيحية والخرائط الذهنية للأمان.
|
| 43 |
+
|
| 44 |
+
---
|
| 45 |
+
|
| 46 |
+
## 🤝 المساهمة | Contributing
|
| 47 |
+
|
| 48 |
+
نحن نؤمن بقوة المجتمع! إذا كان لديك أي تحسين أو إضافة تعليمية، لا تتردد في تقديم Pull Request.
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
## 📄 الترخيص | License
|
| 53 |
+
|
| 54 |
+
هذا المشروع متاح تحت رخصة المشاع الإبداعي (Creative Commons).
|
advanced-security-platform.html
ADDED
|
@@ -0,0 +1,1265 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html dir="rtl" lang="ar">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>منصة الأمان المتقدمة - Advanced Security Platform</title>
|
| 7 |
+
<meta name="description" content="منصة شاملة لأمان الويب مع تقنيات متقدمة في 2025">
|
| 8 |
+
|
| 9 |
+
<!-- الخطوط العربية -->
|
| 10 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 11 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 12 |
+
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
| 13 |
+
|
| 14 |
+
<!-- الأيقونات -->
|
| 15 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 16 |
+
|
| 17 |
+
<!-- CSS الأساسي -->
|
| 18 |
+
<link rel="stylesheet" href="styles/main.css">
|
| 19 |
+
<link rel="stylesheet" href="styles/components.css">
|
| 20 |
+
<link rel="stylesheet" href="styles/responsive.css">
|
| 21 |
+
|
| 22 |
+
<!-- ميتا تاجز للأمان -->
|
| 23 |
+
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self';">
|
| 24 |
+
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
| 25 |
+
<meta http-equiv="X-Frame-Options" content="DENY">
|
| 26 |
+
<meta http-equiv="X-XSS-Protection" content="1; mode=block">
|
| 27 |
+
|
| 28 |
+
<style>
|
| 29 |
+
/* تحسينات خاصة بالمنصة المتقدمة */
|
| 30 |
+
.advanced-platform {
|
| 31 |
+
background: linear-gradient(135deg, #0A0A0A 0%, #1A1A1A 50%, #0A0A0A 100%);
|
| 32 |
+
min-height: 100vh;
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
.ai-features-section {
|
| 36 |
+
background: rgba(0, 224, 213, 0.05);
|
| 37 |
+
border: 1px solid rgba(0, 224, 213, 0.2);
|
| 38 |
+
border-radius: 15px;
|
| 39 |
+
margin: 2rem 0;
|
| 40 |
+
padding: 2rem;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.feature-grid {
|
| 44 |
+
display: grid;
|
| 45 |
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
| 46 |
+
gap: 1.5rem;
|
| 47 |
+
margin-top: 2rem;
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
.feature-card {
|
| 51 |
+
background: linear-gradient(145deg, #1E1E1E, #2A2A2A);
|
| 52 |
+
border: 1px solid rgba(0, 224, 213, 0.3);
|
| 53 |
+
border-radius: 12px;
|
| 54 |
+
padding: 1.5rem;
|
| 55 |
+
transition: all 0.3s ease;
|
| 56 |
+
position: relative;
|
| 57 |
+
overflow: hidden;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
.feature-card::before {
|
| 61 |
+
content: '';
|
| 62 |
+
position: absolute;
|
| 63 |
+
top: 0;
|
| 64 |
+
left: -100%;
|
| 65 |
+
width: 100%;
|
| 66 |
+
height: 100%;
|
| 67 |
+
background: linear-gradient(90deg, transparent, rgba(0, 224, 213, 0.1), transparent);
|
| 68 |
+
transition: left 0.5s ease;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
.feature-card:hover::before {
|
| 72 |
+
left: 100%;
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
.feature-card:hover {
|
| 76 |
+
transform: translateY(-5px);
|
| 77 |
+
box-shadow: 0 10px 30px rgba(0, 224, 213, 0.2);
|
| 78 |
+
border-color: rgba(0, 224, 213, 0.5);
|
| 79 |
+
}
|
| 80 |
+
|
| 81 |
+
.feature-icon {
|
| 82 |
+
width: 50px;
|
| 83 |
+
height: 50px;
|
| 84 |
+
background: linear-gradient(135deg, #00E0D5, #00B8B8);
|
| 85 |
+
border-radius: 12px;
|
| 86 |
+
display: flex;
|
| 87 |
+
align-items: center;
|
| 88 |
+
justify-content: center;
|
| 89 |
+
margin-bottom: 1rem;
|
| 90 |
+
color: #0A0A0A;
|
| 91 |
+
font-size: 1.5rem;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
.feature-title {
|
| 95 |
+
font-size: 1.25rem;
|
| 96 |
+
font-weight: 600;
|
| 97 |
+
color: #E0E0E0;
|
| 98 |
+
margin-bottom: 0.5rem;
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
.feature-description {
|
| 102 |
+
color: #B0B0B0;
|
| 103 |
+
line-height: 1.6;
|
| 104 |
+
margin-bottom: 1rem;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
.feature-status {
|
| 108 |
+
display: inline-flex;
|
| 109 |
+
align-items: center;
|
| 110 |
+
gap: 0.5rem;
|
| 111 |
+
padding: 0.25rem 0.75rem;
|
| 112 |
+
background: rgba(0, 224, 213, 0.1);
|
| 113 |
+
border: 1px solid rgba(0, 224, 213, 0.3);
|
| 114 |
+
border-radius: 20px;
|
| 115 |
+
font-size: 0.875rem;
|
| 116 |
+
color: #00E0D5;
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
.status-indicator {
|
| 120 |
+
width: 8px;
|
| 121 |
+
height: 8px;
|
| 122 |
+
background: #00C851;
|
| 123 |
+
border-radius: 50%;
|
| 124 |
+
animation: pulse 2s infinite;
|
| 125 |
+
}
|
| 126 |
+
|
| 127 |
+
@keyframes pulse {
|
| 128 |
+
0%, 100% { opacity: 1; }
|
| 129 |
+
50% { opacity: 0.5; }
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
.dashboard-preview {
|
| 133 |
+
background: #0D1117;
|
| 134 |
+
border: 1px solid #30363D;
|
| 135 |
+
border-radius: 12px;
|
| 136 |
+
padding: 1rem;
|
| 137 |
+
margin-top: 2rem;
|
| 138 |
+
position: relative;
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
.dashboard-header {
|
| 142 |
+
display: flex;
|
| 143 |
+
align-items: center;
|
| 144 |
+
justify-content: space-between;
|
| 145 |
+
margin-bottom: 1rem;
|
| 146 |
+
padding-bottom: 1rem;
|
| 147 |
+
border-bottom: 1px solid #30363D;
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
.dashboard-title {
|
| 151 |
+
font-size: 1.125rem;
|
| 152 |
+
font-weight: 600;
|
| 153 |
+
color: #F0F6FC;
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
+
.dashboard-controls {
|
| 157 |
+
display: flex;
|
| 158 |
+
gap: 0.5rem;
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
.control-btn {
|
| 162 |
+
padding: 0.5rem 1rem;
|
| 163 |
+
background: #21262D;
|
| 164 |
+
border: 1px solid #30363D;
|
| 165 |
+
border-radius: 6px;
|
| 166 |
+
color: #F0F6FC;
|
| 167 |
+
cursor: pointer;
|
| 168 |
+
transition: all 0.2s ease;
|
| 169 |
+
font-size: 0.875rem;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
.control-btn:hover {
|
| 173 |
+
background: #30363D;
|
| 174 |
+
border-color: #00E0D5;
|
| 175 |
+
}
|
| 176 |
+
|
| 177 |
+
.control-btn.active {
|
| 178 |
+
background: #00E0D5;
|
| 179 |
+
border-color: #00E0D5;
|
| 180 |
+
color: #0A0A0A;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.metrics-grid {
|
| 184 |
+
display: grid;
|
| 185 |
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
| 186 |
+
gap: 1rem;
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
.metric-card {
|
| 190 |
+
background: #161B22;
|
| 191 |
+
border: 1px solid #30363D;
|
| 192 |
+
border-radius: 8px;
|
| 193 |
+
padding: 1rem;
|
| 194 |
+
text-align: center;
|
| 195 |
+
}
|
| 196 |
+
|
| 197 |
+
.metric-value {
|
| 198 |
+
font-size: 2rem;
|
| 199 |
+
font-weight: 700;
|
| 200 |
+
color: #00E0D5;
|
| 201 |
+
margin-bottom: 0.5rem;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
.metric-label {
|
| 205 |
+
color: #8B949E;
|
| 206 |
+
font-size: 0.875rem;
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
.live-chart {
|
| 210 |
+
width: 100%;
|
| 211 |
+
height: 200px;
|
| 212 |
+
background: #0D1117;
|
| 213 |
+
border: 1px solid #30363D;
|
| 214 |
+
border-radius: 8px;
|
| 215 |
+
margin-top: 1rem;
|
| 216 |
+
position: relative;
|
| 217 |
+
overflow: hidden;
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
.chart-line {
|
| 221 |
+
position: absolute;
|
| 222 |
+
bottom: 0;
|
| 223 |
+
left: 0;
|
| 224 |
+
width: 100%;
|
| 225 |
+
height: 100%;
|
| 226 |
+
background: linear-gradient(to top, rgba(0, 224, 213, 0.3), transparent);
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
.chart-points {
|
| 230 |
+
position: absolute;
|
| 231 |
+
top: 0;
|
| 232 |
+
left: 0;
|
| 233 |
+
width: 100%;
|
| 234 |
+
height: 100%;
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
.chart-point {
|
| 238 |
+
position: absolute;
|
| 239 |
+
width: 4px;
|
| 240 |
+
height: 4px;
|
| 241 |
+
background: #00E0D5;
|
| 242 |
+
border-radius: 50%;
|
| 243 |
+
animation: chartPoint 2s infinite;
|
| 244 |
+
}
|
| 245 |
+
|
| 246 |
+
@keyframes chartPoint {
|
| 247 |
+
0%, 100% { transform: scale(1); opacity: 1; }
|
| 248 |
+
50% { transform: scale(1.5); opacity: 0.7; }
|
| 249 |
+
}
|
| 250 |
+
|
| 251 |
+
.training-module {
|
| 252 |
+
background: linear-gradient(145deg, #1A1A1A, #2A2A2A);
|
| 253 |
+
border: 1px solid rgba(0, 224, 213, 0.2);
|
| 254 |
+
border-radius: 12px;
|
| 255 |
+
padding: 1.5rem;
|
| 256 |
+
margin-bottom: 1.5rem;
|
| 257 |
+
}
|
| 258 |
+
|
| 259 |
+
.module-header {
|
| 260 |
+
display: flex;
|
| 261 |
+
align-items: center;
|
| 262 |
+
justify-content: space-between;
|
| 263 |
+
margin-bottom: 1rem;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
.module-title {
|
| 267 |
+
font-size: 1.125rem;
|
| 268 |
+
font-weight: 600;
|
| 269 |
+
color: #E0E0E0;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
.module-progress {
|
| 273 |
+
background: #333;
|
| 274 |
+
border-radius: 10px;
|
| 275 |
+
height: 6px;
|
| 276 |
+
width: 100px;
|
| 277 |
+
overflow: hidden;
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
.progress-bar {
|
| 281 |
+
height: 100%;
|
| 282 |
+
background: linear-gradient(90deg, #00E0D5, #00B8B8);
|
| 283 |
+
border-radius: 10px;
|
| 284 |
+
transition: width 0.3s ease;
|
| 285 |
+
}
|
| 286 |
+
|
| 287 |
+
.interactive-demo {
|
| 288 |
+
background: #0D1117;
|
| 289 |
+
border: 1px solid #30363D;
|
| 290 |
+
border-radius: 8px;
|
| 291 |
+
padding: 1.5rem;
|
| 292 |
+
margin-top: 1rem;
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
.demo-controls {
|
| 296 |
+
display: flex;
|
| 297 |
+
gap: 1rem;
|
| 298 |
+
margin-bottom: 1rem;
|
| 299 |
+
flex-wrap: wrap;
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
.demo-input {
|
| 303 |
+
flex: 1;
|
| 304 |
+
min-width: 200px;
|
| 305 |
+
}
|
| 306 |
+
|
| 307 |
+
.demo-output {
|
| 308 |
+
background: #161B22;
|
| 309 |
+
border: 1px solid #30363D;
|
| 310 |
+
border-radius: 6px;
|
| 311 |
+
padding: 1rem;
|
| 312 |
+
margin-top: 1rem;
|
| 313 |
+
min-height: 60px;
|
| 314 |
+
font-family: 'JetBrains Mono', monospace;
|
| 315 |
+
color: #F0F6FC;
|
| 316 |
+
direction: ltr;
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
.code-example {
|
| 320 |
+
background: #0D1117;
|
| 321 |
+
border: 1px solid #30363D;
|
| 322 |
+
border-radius: 6px;
|
| 323 |
+
margin: 1rem 0;
|
| 324 |
+
overflow: hidden;
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
.code-header {
|
| 328 |
+
background: #21262D;
|
| 329 |
+
padding: 0.5rem 1rem;
|
| 330 |
+
border-bottom: 1px solid #30363D;
|
| 331 |
+
display: flex;
|
| 332 |
+
align-items: center;
|
| 333 |
+
justify-content: space-between;
|
| 334 |
+
font-size: 0.875rem;
|
| 335 |
+
color: #8B949E;
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
.copy-btn {
|
| 339 |
+
background: none;
|
| 340 |
+
border: 1px solid #30363D;
|
| 341 |
+
border-radius: 4px;
|
| 342 |
+
padding: 0.25rem 0.5rem;
|
| 343 |
+
color: #8B949E;
|
| 344 |
+
cursor: pointer;
|
| 345 |
+
transition: all 0.2s ease;
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
.copy-btn:hover {
|
| 349 |
+
background: #30363D;
|
| 350 |
+
color: #F0F6FC;
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
.code-content {
|
| 354 |
+
padding: 1rem;
|
| 355 |
+
overflow-x: auto;
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
.code-content code {
|
| 359 |
+
font-family: 'JetBrains Mono', monospace;
|
| 360 |
+
color: #F0F6FC;
|
| 361 |
+
direction: ltr;
|
| 362 |
+
display: block;
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
.alert-box {
|
| 366 |
+
background: rgba(255, 68, 68, 0.1);
|
| 367 |
+
border: 1px solid rgba(255, 68, 68, 0.3);
|
| 368 |
+
border-radius: 8px;
|
| 369 |
+
padding: 1rem;
|
| 370 |
+
margin: 1rem 0;
|
| 371 |
+
color: #FF6B6B;
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
.info-box {
|
| 375 |
+
background: rgba(0, 224, 213, 0.1);
|
| 376 |
+
border: 1px solid rgba(0, 224, 213, 0.3);
|
| 377 |
+
border-radius: 8px;
|
| 378 |
+
padding: 1rem;
|
| 379 |
+
margin: 1rem 0;
|
| 380 |
+
color: #00E0D5;
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
.success-box {
|
| 384 |
+
background: rgba(0, 200, 81, 0.1);
|
| 385 |
+
border: 1px solid rgba(0, 200, 81, 0.3);
|
| 386 |
+
border-radius: 8px;
|
| 387 |
+
padding: 1rem;
|
| 388 |
+
margin: 1rem 0;
|
| 389 |
+
color: #00C851;
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
.warning-box {
|
| 393 |
+
background: rgba(255, 187, 51, 0.1);
|
| 394 |
+
border: 1px solid rgba(255, 187, 51, 0.3);
|
| 395 |
+
border-radius: 8px;
|
| 396 |
+
padding: 1rem;
|
| 397 |
+
margin: 1rem 0;
|
| 398 |
+
color: #FFBB33;
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
@media (max-width: 768px) {
|
| 402 |
+
.feature-grid {
|
| 403 |
+
grid-template-columns: 1fr;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
.metrics-grid {
|
| 407 |
+
grid-template-columns: repeat(2, 1fr);
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
.demo-controls {
|
| 411 |
+
flex-direction: column;
|
| 412 |
+
}
|
| 413 |
+
|
| 414 |
+
.dashboard-controls {
|
| 415 |
+
flex-wrap: wrap;
|
| 416 |
+
}
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
/* تأثيرات متقدمة */
|
| 420 |
+
.glow-effect {
|
| 421 |
+
box-shadow: 0 0 20px rgba(0, 224, 213, 0.3);
|
| 422 |
+
animation: glow 2s ease-in-out infinite alternate;
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
@keyframes glow {
|
| 426 |
+
from { box-shadow: 0 0 20px rgba(0, 224, 213, 0.3); }
|
| 427 |
+
to { box-shadow: 0 0 30px rgba(0, 224, 213, 0.6); }
|
| 428 |
+
}
|
| 429 |
+
|
| 430 |
+
.slide-in {
|
| 431 |
+
animation: slideIn 0.5s ease-out;
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
@keyframes slideIn {
|
| 435 |
+
from { transform: translateY(20px); opacity: 0; }
|
| 436 |
+
to { transform: translateY(0); opacity: 1; }
|
| 437 |
+
}
|
| 438 |
+
|
| 439 |
+
.fade-in {
|
| 440 |
+
animation: fadeIn 0.5s ease-out;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
@keyframes fadeIn {
|
| 444 |
+
from { opacity: 0; }
|
| 445 |
+
to { opacity: 1; }
|
| 446 |
+
}
|
| 447 |
+
</style>
|
| 448 |
+
</head>
|
| 449 |
+
<body class="advanced-platform">
|
| 450 |
+
<!-- شريط التنقل المتقدم -->
|
| 451 |
+
<nav class="navbar advanced-navbar">
|
| 452 |
+
<div class="nav-container">
|
| 453 |
+
<div class="nav-brand">
|
| 454 |
+
<i class="fas fa-shield-alt"></i>
|
| 455 |
+
<span>منصة الأمان المتقدمة</span>
|
| 456 |
+
</div>
|
| 457 |
+
<div class="nav-menu">
|
| 458 |
+
<a href="#ai-features" class="nav-link">
|
| 459 |
+
<i class="fas fa-robot"></i>
|
| 460 |
+
<span>الميزات الذكية</span>
|
| 461 |
+
</a>
|
| 462 |
+
<a href="#dashboard" class="nav-link">
|
| 463 |
+
<i class="fas fa-chart-line"></i>
|
| 464 |
+
<span>لوحة المعلومات</span>
|
| 465 |
+
</a>
|
| 466 |
+
<a href="#training" class="nav-link">
|
| 467 |
+
<i class="fas fa-graduation-cap"></i>
|
| 468 |
+
<span>التدريب</span>
|
| 469 |
+
</a>
|
| 470 |
+
<a href="#tools" class="nav-link">
|
| 471 |
+
<i class="fas fa-tools"></i>
|
| 472 |
+
<span>الأدوات</span>
|
| 473 |
+
</a>
|
| 474 |
+
</div>
|
| 475 |
+
<div class="nav-actions">
|
| 476 |
+
<button class="btn btn-primary" onclick="initializeAdvancedFeatures()">
|
| 477 |
+
<i class="fas fa-play"></i>
|
| 478 |
+
تشغيل الميزات المتقدمة
|
| 479 |
+
</button>
|
| 480 |
+
</div>
|
| 481 |
+
</div>
|
| 482 |
+
</nav>
|
| 483 |
+
|
| 484 |
+
<!-- القسم الرئيسي -->
|
| 485 |
+
<main class="main-content">
|
| 486 |
+
<!-- القسم البطل -->
|
| 487 |
+
<section class="hero-section">
|
| 488 |
+
<div class="hero-content">
|
| 489 |
+
<h1 class="hero-title">
|
| 490 |
+
منصة الأمان المتقدمة
|
| 491 |
+
<span class="text-gradient">2025</span>
|
| 492 |
+
</h1>
|
| 493 |
+
<p class="hero-description">
|
| 494 |
+
نظام شامل ومتطور لأمان الويب مع تقنيات الذكاء الاصطناعي والتعلم الآلي
|
| 495 |
+
للمراقبة في الوقت الفعلي والتحليل الذكي للتهديدات
|
| 496 |
+
</p>
|
| 497 |
+
<div class="hero-features">
|
| 498 |
+
<div class="feature-badge">
|
| 499 |
+
<i class="fas fa-brain"></i>
|
| 500 |
+
<span>ذكاء اصطناعي متقدم</span>
|
| 501 |
+
</div>
|
| 502 |
+
<div class="feature-badge">
|
| 503 |
+
<i class="fas fa-chart-line"></i>
|
| 504 |
+
<span>مراقبة في الوقت الفعلي</span>
|
| 505 |
+
</div>
|
| 506 |
+
<div class="feature-badge">
|
| 507 |
+
<i class="fas fa-graduation-cap"></i>
|
| 508 |
+
<span>تدريب تفاعلي</span>
|
| 509 |
+
</div>
|
| 510 |
+
</div>
|
| 511 |
+
</div>
|
| 512 |
+
</section>
|
| 513 |
+
|
| 514 |
+
<!-- قسم الميزات الذكية -->
|
| 515 |
+
<section id="ai-features" class="ai-features-section">
|
| 516 |
+
<div class="container">
|
| 517 |
+
<h2 class="section-title">الميزات الذكية المتقدمة</h2>
|
| 518 |
+
<p class="section-description">
|
| 519 |
+
استفد من أحدث تقنيات الذكاء الاصطناعي في أمان الويب
|
| 520 |
+
</p>
|
| 521 |
+
|
| 522 |
+
<div class="feature-grid">
|
| 523 |
+
<!-- محلل التهديدات الذكي -->
|
| 524 |
+
<div class="feature-card" data-aos="fade-up" data-aos-delay="100">
|
| 525 |
+
<div class="feature-icon">
|
| 526 |
+
<i class="fas fa-search"></i>
|
| 527 |
+
</div>
|
| 528 |
+
<h3 class="feature-title">محلل التهديدات الذكي</h3>
|
| 529 |
+
<p class="feature-description">
|
| 530 |
+
تحليل ذكي للتهديدات باستخدام الذكاء الاصطناعي مع تحديد المخاطر والتوصيات التلقائية
|
| 531 |
+
</p>
|
| 532 |
+
<div class="feature-status">
|
| 533 |
+
<div class="status-indicator"></div>
|
| 534 |
+
<span>نشط</span>
|
| 535 |
+
</div>
|
| 536 |
+
<div class="feature-demo">
|
| 537 |
+
<button class="btn btn-outline" onclick="demoThreatAnalyzer()">
|
| 538 |
+
<i class="fas fa-play"></i>
|
| 539 |
+
تجربة
|
| 540 |
+
</button>
|
| 541 |
+
</div>
|
| 542 |
+
</div>
|
| 543 |
+
|
| 544 |
+
<!-- المراقبة في الوقت الفعلي -->
|
| 545 |
+
<div class="feature-card" data-aos="fade-up" data-aos-delay="200">
|
| 546 |
+
<div class="feature-icon">
|
| 547 |
+
<i class="fas fa-broadcast-tower"></i>
|
| 548 |
+
</div>
|
| 549 |
+
<h3 class="feature-title">المراقبة في الوقت الفعلي</h3>
|
| 550 |
+
<p class="feature-description">
|
| 551 |
+
مراقبة أمنية متطورة مع تنبيهات فورية وتحليل أداء متقدم
|
| 552 |
+
</p>
|
| 553 |
+
<div class="feature-status">
|
| 554 |
+
<div class="status-indicator"></div>
|
| 555 |
+
<span>نشط</span>
|
| 556 |
+
</div>
|
| 557 |
+
<div class="feature-demo">
|
| 558 |
+
<button class="btn btn-outline" onclick="demoRealTimeMonitoring()">
|
| 559 |
+
<i class="fas fa-play"></i>
|
| 560 |
+
تجربة
|
| 561 |
+
</button>
|
| 562 |
+
</div>
|
| 563 |
+
</div>
|
| 564 |
+
|
| 565 |
+
<!-- مولد السياسات الذكي -->
|
| 566 |
+
<div class="feature-card" data-aos="fade-up" data-aos-delay="300">
|
| 567 |
+
<div class="feature-icon">
|
| 568 |
+
<i class="fas fa-cogs"></i>
|
| 569 |
+
</div>
|
| 570 |
+
<h3 class="feature-title">مولد السياسات الذكي</h3>
|
| 571 |
+
<p class="feature-description">
|
| 572 |
+
توليد سياسات أمان مخصصة تلقائياً بناءً على تحليل الموقع
|
| 573 |
+
</p>
|
| 574 |
+
<div class="feature-status">
|
| 575 |
+
<div class="status-indicator"></div>
|
| 576 |
+
<span>نشط</span>
|
| 577 |
+
</div>
|
| 578 |
+
<div class="feature-demo">
|
| 579 |
+
<button class="btn btn-outline" onclick="demoSmartPolicyGenerator()">
|
| 580 |
+
<i class="fas fa-play"></i>
|
| 581 |
+
تجربة
|
| 582 |
+
</button>
|
| 583 |
+
</div>
|
| 584 |
+
</div>
|
| 585 |
+
|
| 586 |
+
<!-- التدريب التفاعلي -->
|
| 587 |
+
<div class="feature-card" data-aos="fade-up" data-aos-delay="400">
|
| 588 |
+
<div class="feature-icon">
|
| 589 |
+
<i class="fas fa-gamepad"></i>
|
| 590 |
+
</div>
|
| 591 |
+
<h3 class="feature-title">التدريب التفاعلي</h3>
|
| 592 |
+
<p class="feature-description">
|
| 593 |
+
دروس تفاعلية ومحاك��ة أمنية مع سيناريوهات واقعية
|
| 594 |
+
</p>
|
| 595 |
+
<div class="feature-status">
|
| 596 |
+
<div class="status-indicator"></div>
|
| 597 |
+
<span>نشط</span>
|
| 598 |
+
</div>
|
| 599 |
+
<div class="feature-demo">
|
| 600 |
+
<button class="btn btn-outline" onclick="demoInteractiveTraining()">
|
| 601 |
+
<i class="fas fa-play"></i>
|
| 602 |
+
تجربة
|
| 603 |
+
</button>
|
| 604 |
+
</div>
|
| 605 |
+
</div>
|
| 606 |
+
</div>
|
| 607 |
+
</div>
|
| 608 |
+
</section>
|
| 609 |
+
|
| 610 |
+
<!-- قسم لوحة المعلومات -->
|
| 611 |
+
<section id="dashboard" class="dashboard-section">
|
| 612 |
+
<div class="container">
|
| 613 |
+
<h2 class="section-title">لوحة المعلومات الذكية</h2>
|
| 614 |
+
<p class="section-description">
|
| 615 |
+
مراقبة شاملة للمؤشرات الأمنية والأداء في الوقت الفعلي
|
| 616 |
+
</p>
|
| 617 |
+
|
| 618 |
+
<div class="dashboard-preview">
|
| 619 |
+
<div class="dashboard-header">
|
| 620 |
+
<h3 class="dashboard-title">
|
| 621 |
+
<i class="fas fa-chart-area"></i>
|
| 622 |
+
نظرة عامة على الأمان
|
| 623 |
+
</h3>
|
| 624 |
+
<div class="dashboard-controls">
|
| 625 |
+
<button class="control-btn active" onclick="switchDashboardView('overview')">نظرة عامة</button>
|
| 626 |
+
<button class="control-btn" onclick="switchDashboardView('threats')">التهديدات</button>
|
| 627 |
+
<button class="control-btn" onclick="switchDashboardView('compliance')">الامتثال</button>
|
| 628 |
+
<button class="control-btn" onclick="switchDashboardView('performance')">الأداء</button>
|
| 629 |
+
</div>
|
| 630 |
+
</div>
|
| 631 |
+
|
| 632 |
+
<div class="metrics-grid" id="dashboard-metrics">
|
| 633 |
+
<div class="metric-card">
|
| 634 |
+
<div class="metric-value">95</div>
|
| 635 |
+
<div class="metric-label">درجة الأمان</div>
|
| 636 |
+
</div>
|
| 637 |
+
<div class="metric-card">
|
| 638 |
+
<div class="metric-value">12</div>
|
| 639 |
+
<div class="metric-label">التهديدات اليومية</div>
|
| 640 |
+
</div>
|
| 641 |
+
<div class="metric-card">
|
| 642 |
+
<div class="metric-value">99.9%</div>
|
| 643 |
+
<div class="metric-label">وقت التشغيل</div>
|
| 644 |
+
</div>
|
| 645 |
+
<div class="metric-card">
|
| 646 |
+
<div class="metric-value">3</div>
|
| 647 |
+
<div class="metric-label">انتهاكات حرجة</div>
|
| 648 |
+
</div>
|
| 649 |
+
</div>
|
| 650 |
+
|
| 651 |
+
<div class="live-chart">
|
| 652 |
+
<div class="chart-line"></div>
|
| 653 |
+
<div class="chart-points">
|
| 654 |
+
<div class="chart-point" style="left: 10%; bottom: 20%;"></div>
|
| 655 |
+
<div class="chart-point" style="left: 20%; bottom: 40%;"></div>
|
| 656 |
+
<div class="chart-point" style="left: 30%; bottom: 30%;"></div>
|
| 657 |
+
<div class="chart-point" style="left: 40%; bottom: 60%;"></div>
|
| 658 |
+
<div class="chart-point" style="left: 50%; bottom: 50%;"></div>
|
| 659 |
+
<div class="chart-point" style="left: 60%; bottom: 70%;"></div>
|
| 660 |
+
<div class="chart-point" style="left: 70%; bottom: 45%;"></div>
|
| 661 |
+
<div class="chart-point" style="left: 80%; bottom: 65%;"></div>
|
| 662 |
+
<div class="chart-point" style="left: 90%; bottom: 55%;"></div>
|
| 663 |
+
</div>
|
| 664 |
+
</div>
|
| 665 |
+
</div>
|
| 666 |
+
</div>
|
| 667 |
+
</section>
|
| 668 |
+
|
| 669 |
+
<!-- قسم التدريب -->
|
| 670 |
+
<section id="training" class="training-section">
|
| 671 |
+
<div class="container">
|
| 672 |
+
<h2 class="section-title">منصة التدريب التفاعلي</h2>
|
| 673 |
+
<p class="section-description">
|
| 674 |
+
تعلم أمان الويب من خلال تجارب تفاعلية ومحاكاة واقعية
|
| 675 |
+
</p>
|
| 676 |
+
|
| 677 |
+
<div class="training-modules">
|
| 678 |
+
<!-- وحدة أساسيات الأمان -->
|
| 679 |
+
<div class="training-module">
|
| 680 |
+
<div class="module-header">
|
| 681 |
+
<h3 class="module-title">
|
| 682 |
+
<i class="fas fa-shield-alt"></i>
|
| 683 |
+
أساسيات أمان الويب
|
| 684 |
+
</h3>
|
| 685 |
+
<div class="module-progress">
|
| 686 |
+
<div class="progress-bar" style="width: 75%"></div>
|
| 687 |
+
</div>
|
| 688 |
+
</div>
|
| 689 |
+
<p class="module-description">
|
| 690 |
+
تعلم المفاهيم الأساسية لأمان الويب وأهم التهديدات وكيفية الحماية منها
|
| 691 |
+
</p>
|
| 692 |
+
<div class="module-stats">
|
| 693 |
+
<span><i class="fas fa-clock"></i> 30 دقيقة</span>
|
| 694 |
+
<span><i class="fas fa-signal"></i> مبتدئ</span>
|
| 695 |
+
<span><i class="fas fa-check-circle"></i> 3 دروس مكتملة</span>
|
| 696 |
+
</div>
|
| 697 |
+
<div class="module-actions">
|
| 698 |
+
<button class="btn btn-primary" onclick="startTrainingModule('fundamentals')">
|
| 699 |
+
<i class="fas fa-play"></i>
|
| 700 |
+
متابعة التعلم
|
| 701 |
+
</button>
|
| 702 |
+
<button class="btn btn-outline" onclick="previewTrainingModule('fundamentals')">
|
| 703 |
+
<i class="fas fa-eye"></i>
|
| 704 |
+
معاينة
|
| 705 |
+
</button>
|
| 706 |
+
</div>
|
| 707 |
+
</div>
|
| 708 |
+
|
| 709 |
+
<!-- وحدة XSS -->
|
| 710 |
+
<div class="training-module">
|
| 711 |
+
<div class="module-header">
|
| 712 |
+
<h3 class="module-title">
|
| 713 |
+
<i class="fas fa-bug"></i>
|
| 714 |
+
منع هجمات XSS
|
| 715 |
+
</h3>
|
| 716 |
+
<div class="module-progress">
|
| 717 |
+
<div class="progress-bar" style="width: 25%"></div>
|
| 718 |
+
</div>
|
| 719 |
+
</div>
|
| 720 |
+
<p class="module-description">
|
| 721 |
+
فهم هجمات Cross-Site Scripting وكيفية الحماية منها باستخدام CSP وأفضل الممارسات
|
| 722 |
+
</p>
|
| 723 |
+
<div class="module-stats">
|
| 724 |
+
<span><i class="fas fa-clock"></i> 45 دقيقة</span>
|
| 725 |
+
<span><i class="fas fa-signal"></i> متوسط</span>
|
| 726 |
+
<span><i class="fas fa-trophy"></i> شهادة متاحة</span>
|
| 727 |
+
</div>
|
| 728 |
+
<div class="module-actions">
|
| 729 |
+
<button class="btn btn-primary" onclick="startTrainingModule('xss')">
|
| 730 |
+
<i class="fas fa-play"></i>
|
| 731 |
+
بدء التعلم
|
| 732 |
+
</button>
|
| 733 |
+
<button class="btn btn-outline" onclick="previewTrainingModule('xss')">
|
| 734 |
+
<i class="fas fa-eye"></i>
|
| 735 |
+
معاينة
|
| 736 |
+
</button>
|
| 737 |
+
</div>
|
| 738 |
+
</div>
|
| 739 |
+
</div>
|
| 740 |
+
</div>
|
| 741 |
+
</section>
|
| 742 |
+
|
| 743 |
+
<!-- قسم الأدوات المتقدمة -->
|
| 744 |
+
<section id="tools" class="tools-section">
|
| 745 |
+
<div class="container">
|
| 746 |
+
<h2 class="section-title">الأدوات المتقدمة</h2>
|
| 747 |
+
<p class="section-description">
|
| 748 |
+
مجموعة شاملة من الأدوات المتطورة لحماية وتطوير التطبيقات
|
| 749 |
+
</p>
|
| 750 |
+
|
| 751 |
+
<div class="tools-grid">
|
| 752 |
+
<!-- أداة محاكاة XSS -->
|
| 753 |
+
<div class="tool-card">
|
| 754 |
+
<div class="tool-header">
|
| 755 |
+
<div class="tool-icon">
|
| 756 |
+
<i class="fas fa-code"></i>
|
| 757 |
+
</div>
|
| 758 |
+
<h3 class="tool-title">محاكي XSS الآمن</h3>
|
| 759 |
+
</div>
|
| 760 |
+
<div class="tool-description">
|
| 761 |
+
تجربة تفاعلية آمنة لفهم هجمات XSS وكيفية الحماية منها
|
| 762 |
+
</div>
|
| 763 |
+
<div class="interactive-demo">
|
| 764 |
+
<div class="demo-controls">
|
| 765 |
+
<input type="text" class="demo-input" placeholder="أدخل تعليقك الآمن..." id="xss-demo-input">
|
| 766 |
+
<button class="btn btn-secondary" onclick="simulateXSSAttack()">
|
| 767 |
+
<i class="fas fa-play"></i>
|
| 768 |
+
تجربة آمنة
|
| 769 |
+
</button>
|
| 770 |
+
</div>
|
| 771 |
+
<div class="demo-output" id="xss-demo-output">
|
| 772 |
+
<em>النت��جة ستظهر هنا...</em>
|
| 773 |
+
</div>
|
| 774 |
+
</div>
|
| 775 |
+
</div>
|
| 776 |
+
|
| 777 |
+
<!-- مولد CSP -->
|
| 778 |
+
<div class="tool-card">
|
| 779 |
+
<div class="tool-header">
|
| 780 |
+
<div class="tool-icon">
|
| 781 |
+
<i class="fas fa-shield-virus"></i>
|
| 782 |
+
</div>
|
| 783 |
+
<h3 class="tool-title">مولد CSP الذكي</h3>
|
| 784 |
+
</div>
|
| 785 |
+
<div class="tool-description">
|
| 786 |
+
إنشاء سياسات أمان محتوى مخصصة بناءً على احتياجات موقعك
|
| 787 |
+
</div>
|
| 788 |
+
<div class="interactive-demo">
|
| 789 |
+
<div class="demo-controls">
|
| 790 |
+
<select class="demo-input" id="csp-template">
|
| 791 |
+
<option value="basic">أساسي</option>
|
| 792 |
+
<option value="strict">صارم</option>
|
| 793 |
+
<option value="modern">حديث</option>
|
| 794 |
+
<option value="ecommerce">تجارة إلكترونية</option>
|
| 795 |
+
</select>
|
| 796 |
+
<button class="btn btn-secondary" onclick="generateCSP()">
|
| 797 |
+
<i class="fas fa-magic"></i>
|
| 798 |
+
توليد السياسة
|
| 799 |
+
</button>
|
| 800 |
+
</div>
|
| 801 |
+
<div class="demo-output" id="csp-demo-output">
|
| 802 |
+
<code>سياسة CSP ستظهر هنا...</code>
|
| 803 |
+
</div>
|
| 804 |
+
</div>
|
| 805 |
+
</div>
|
| 806 |
+
|
| 807 |
+
<!-- فاحص الأمان -->
|
| 808 |
+
<div class="tool-card">
|
| 809 |
+
<div class="tool-header">
|
| 810 |
+
<div class="tool-icon">
|
| 811 |
+
<i class="fas fa-stethoscope"></i>
|
| 812 |
+
</div>
|
| 813 |
+
<h3 class="tool-title">فاحص الأمان الذكي</h3>
|
| 814 |
+
</div>
|
| 815 |
+
<div class="tool-description">
|
| 816 |
+
تحليل شامل للموقع واكتشاف الثغرات الأمنية المحتملة
|
| 817 |
+
</div>
|
| 818 |
+
<div class="interactive-demo">
|
| 819 |
+
<div class="demo-controls">
|
| 820 |
+
<input type="url" class="demo-input" placeholder="https://example.com" id="scan-demo-input">
|
| 821 |
+
<button class="btn btn-secondary" onclick="scanWebsite()">
|
| 822 |
+
<i class="fas fa-search"></i>
|
| 823 |
+
فحص الموقع
|
| 824 |
+
</button>
|
| 825 |
+
</div>
|
| 826 |
+
<div class="demo-output" id="scan-demo-output">
|
| 827 |
+
<em>نتائج الفحص ستظهر هنا...</em>
|
| 828 |
+
</div>
|
| 829 |
+
</div>
|
| 830 |
+
</div>
|
| 831 |
+
</div>
|
| 832 |
+
</div>
|
| 833 |
+
</section>
|
| 834 |
+
|
| 835 |
+
<!-- قسم الإحصائيات -->
|
| 836 |
+
<section class="stats-section">
|
| 837 |
+
<div class="container">
|
| 838 |
+
<h2 class="section-title">إحصائيات المنصة</h2>
|
| 839 |
+
<div class="stats-grid">
|
| 840 |
+
<div class="stat-card">
|
| 841 |
+
<div class="stat-icon">
|
| 842 |
+
<i class="fas fa-shield-alt"></i>
|
| 843 |
+
</div>
|
| 844 |
+
<div class="stat-value">50,000+</div>
|
| 845 |
+
<div class="stat-label">موقع محمي</div>
|
| 846 |
+
</div>
|
| 847 |
+
<div class="stat-card">
|
| 848 |
+
<div class="stat-icon">
|
| 849 |
+
<i class="fas fa-bug"></i>
|
| 850 |
+
</div>
|
| 851 |
+
<div class="stat-value">1M+</div>
|
| 852 |
+
<div class="stat-label">تهديد تم اكتشافه</div>
|
| 853 |
+
</div>
|
| 854 |
+
<div class="stat-card">
|
| 855 |
+
<div class="stat-icon">
|
| 856 |
+
<i class="fas fa-users"></i>
|
| 857 |
+
</div>
|
| 858 |
+
<div class="stat-value">25,000+</div>
|
| 859 |
+
<div class="stat-label">مطور مدرب</div>
|
| 860 |
+
</div>
|
| 861 |
+
<div class="stat-card">
|
| 862 |
+
<div class="stat-icon">
|
| 863 |
+
<i class="fas fa-clock"></i>
|
| 864 |
+
</div>
|
| 865 |
+
<div class="stat-value">99.9%</div>
|
| 866 |
+
<div class="stat-label">وقت التشغيل</div>
|
| 867 |
+
</div>
|
| 868 |
+
</div>
|
| 869 |
+
</div>
|
| 870 |
+
</section>
|
| 871 |
+
</main>
|
| 872 |
+
|
| 873 |
+
<!-- تذييل متقدم -->
|
| 874 |
+
<footer class="advanced-footer">
|
| 875 |
+
<div class="container">
|
| 876 |
+
<div class="footer-content">
|
| 877 |
+
<div class="footer-section">
|
| 878 |
+
<h4>منصة الأمان المتقدمة</h4>
|
| 879 |
+
<p>أحدث التقنيات في أمان الويب لحماية تطبيقاتك وموقعك</p>
|
| 880 |
+
<div class="social-links">
|
| 881 |
+
<a href="#" class="social-link"><i class="fab fa-github"></i></a>
|
| 882 |
+
<a href="#" class="social-link"><i class="fab fa-twitter"></i></a>
|
| 883 |
+
<a href="#" class="social-link"><i class="fab fa-linkedin"></i></a>
|
| 884 |
+
</div>
|
| 885 |
+
</div>
|
| 886 |
+
<div class="footer-section">
|
| 887 |
+
<h4>الأدوات</h4>
|
| 888 |
+
<ul class="footer-links">
|
| 889 |
+
<li><a href="#">محلل التهديدات</a></li>
|
| 890 |
+
<li><a href="#">مولد السياسات</a></li>
|
| 891 |
+
<li><a href="#">فاحص الأمان</a></li>
|
| 892 |
+
<li><a href="#">لوحة المعلومات</a></li>
|
| 893 |
+
</ul>
|
| 894 |
+
</div>
|
| 895 |
+
<div class="footer-section">
|
| 896 |
+
<h4>التدريب</h4>
|
| 897 |
+
<ul class="footer-links">
|
| 898 |
+
<li><a href="#">دروس تفاعلية</a></li>
|
| 899 |
+
<li><a href="#">محاكاة أمنية</a></li>
|
| 900 |
+
<li><a href="#">شهادات</a></li>
|
| 901 |
+
<li><a href="#">ورش عمل</a></li>
|
| 902 |
+
</ul>
|
| 903 |
+
</div>
|
| 904 |
+
<div class="footer-section">
|
| 905 |
+
<h4>المساعدة</h4>
|
| 906 |
+
<ul class="footer-links">
|
| 907 |
+
<li><a href="#">الوثائق</a></li>
|
| 908 |
+
<li><a href="#">الدعم الفني</a></li>
|
| 909 |
+
<li><a href="#">الأسئلة الشائعة</a></li>
|
| 910 |
+
<li><a href="#">اتصل بنا</a></li>
|
| 911 |
+
</ul>
|
| 912 |
+
</div>
|
| 913 |
+
</div>
|
| 914 |
+
<div class="footer-bottom">
|
| 915 |
+
<p>© 2025 منصة الأمان المتقدمة. جميع الحقوق محفوظة.</p>
|
| 916 |
+
<p>طُور بواسطة MiniMax Agent</p>
|
| 917 |
+
</div>
|
| 918 |
+
</div>
|
| 919 |
+
</footer>
|
| 920 |
+
|
| 921 |
+
<!-- سكريبت JavaScript الأساسي -->
|
| 922 |
+
<script src="js/main.js"></script>
|
| 923 |
+
<script src="js/components.js"></script>
|
| 924 |
+
<script src="js/tools.js"></script>
|
| 925 |
+
|
| 926 |
+
<!-- سكريبت الميزات المتقدمة -->
|
| 927 |
+
<script src="js/ai-threat-analyzer.js"></script>
|
| 928 |
+
<script src="js/real-time-monitor.js"></script>
|
| 929 |
+
<script src="js/smart-policy-generator.js"></script>
|
| 930 |
+
<script src="js/security-training.js"></script>
|
| 931 |
+
<script src="js/security-dashboard.js"></script>
|
| 932 |
+
|
| 933 |
+
<!-- سكريبت التفاعل المتقدم -->
|
| 934 |
+
<script>
|
| 935 |
+
// تهيئة المنصة المتقدمة
|
| 936 |
+
let securityTraining, securityDashboard, aiAnalyzer, policyGenerator, realTimeMonitor;
|
| 937 |
+
|
| 938 |
+
function initializeAdvancedFeatures() {
|
| 939 |
+
showNotification('جاري تهيئة الميزات المتقدمة...', 'info');
|
| 940 |
+
|
| 941 |
+
// تهيئة المكونات
|
| 942 |
+
securityTraining = new SecurityTraining();
|
| 943 |
+
securityDashboard = new SecurityDashboard();
|
| 944 |
+
aiAnalyzer = new AIThreatAnalyzer();
|
| 945 |
+
policyGenerator = new SmartPolicyGenerator();
|
| 946 |
+
realTimeMonitor = securityMonitor;
|
| 947 |
+
|
| 948 |
+
// طلب إذن الإشعارات
|
| 949 |
+
if ('Notification' in window) {
|
| 950 |
+
Notification.requestPermission();
|
| 951 |
+
}
|
| 952 |
+
|
| 953 |
+
// تفعيل المراقبة في الوقت الفعلي
|
| 954 |
+
if (realTimeMonitor) {
|
| 955 |
+
realTimeMonitor.startMonitoring();
|
| 956 |
+
}
|
| 957 |
+
|
| 958 |
+
showNotification('تم تفعيل جميع الميزات المتقدمة بنجاح!', 'success');
|
| 959 |
+
|
| 960 |
+
// تأثيرات بصرية
|
| 961 |
+
document.querySelectorAll('.feature-card').forEach((card, index) => {
|
| 962 |
+
setTimeout(() => {
|
| 963 |
+
card.classList.add('slide-in');
|
| 964 |
+
}, index * 200);
|
| 965 |
+
});
|
| 966 |
+
}
|
| 967 |
+
|
| 968 |
+
// وظائف التجارب التفاعلية
|
| 969 |
+
function demoThreatAnalyzer() {
|
| 970 |
+
const sampleContent = '<script>alert("XSS Attack!")</script>';
|
| 971 |
+
const result = aiAnalyzer.analyzeContent(sampleContent, 'demo');
|
| 972 |
+
|
| 973 |
+
result.then(analysis => {
|
| 974 |
+
showDemoResult('threat-analyzer', `
|
| 975 |
+
<div class="alert-box">
|
| 976 |
+
<h4>نتائج التحليل</h4>
|
| 977 |
+
<p><strong>درجة المخاطر:</strong> ${analysis.riskScore}%</p>
|
| 978 |
+
<p><strong>التهديدات المكتشفة:</strong> ${analysis.threats.length}</p>
|
| 979 |
+
<ul>
|
| 980 |
+
${analysis.threats.map(threat =>
|
| 981 |
+
`<li>${threat.type} - ${threat.severity}</li>`
|
| 982 |
+
).join('')}
|
| 983 |
+
</ul>
|
| 984 |
+
</div>
|
| 985 |
+
`);
|
| 986 |
+
}).catch(error => {
|
| 987 |
+
showDemoResult('threat-analyzer', `
|
| 988 |
+
<div class="warning-box">
|
| 989 |
+
<p>خطأ في التحليل: ${error.message}</p>
|
| 990 |
+
</div>
|
| 991 |
+
`);
|
| 992 |
+
});
|
| 993 |
+
}
|
| 994 |
+
|
| 995 |
+
function demoRealTimeMonitoring() {
|
| 996 |
+
showDemoResult('real-time-monitor', `
|
| 997 |
+
<div class="info-box">
|
| 998 |
+
<h4>المراقبة في الوقت الفعلي نشطة</h4>
|
| 999 |
+
<p>جاري مراقبة الطلبات والأخطاء والتنبيهات الأمنية...</p>
|
| 1000 |
+
<div class="metrics-grid" style="margin-top: 1rem;">
|
| 1001 |
+
<div class="metric-card">
|
| 1002 |
+
<div class="metric-value">1,234</div>
|
| 1003 |
+
<div class="metric-label">طلبات اليوم</div>
|
| 1004 |
+
</div>
|
| 1005 |
+
<div class="metric-card">
|
| 1006 |
+
<div class="metric-value">5</div>
|
| 1007 |
+
<div class="metric-label">تنبيهات نشطة</div>
|
| 1008 |
+
</div>
|
| 1009 |
+
<div class="metric-card">
|
| 1010 |
+
<div class="metric-value">250ms</div>
|
| 1011 |
+
<div class="metric-label">متوسط الاستجابة</div>
|
| 1012 |
+
</div>
|
| 1013 |
+
</div>
|
| 1014 |
+
</div>
|
| 1015 |
+
`);
|
| 1016 |
+
|
| 1017 |
+
// محاكاة تنبيه
|
| 1018 |
+
setTimeout(() => {
|
| 1019 |
+
showNotification('تنبيه أمني: محاولة XSS مكتشفة', 'warning');
|
| 1020 |
+
}, 2000);
|
| 1021 |
+
}
|
| 1022 |
+
|
| 1023 |
+
function demoSmartPolicyGenerator() {
|
| 1024 |
+
const sampleUrl = 'https://example.com';
|
| 1025 |
+
const result = policyGenerator.generatePolicy(sampleUrl);
|
| 1026 |
+
|
| 1027 |
+
result.then(policy => {
|
| 1028 |
+
showDemoResult('policy-generator', `
|
| 1029 |
+
<div class="success-box">
|
| 1030 |
+
<h4>سياسة الأمان المولدة</h4>
|
| 1031 |
+
<p><strong>نوع الموقع:</strong> ${policy.websiteType}</p>
|
| 1032 |
+
<p><strong>سياسة CSP:</strong></p>
|
| 1033 |
+
<div class="code-example">
|
| 1034 |
+
<code>${policy.policy.csp}</code>
|
| 1035 |
+
</div>
|
| 1036 |
+
<p><strong>عدد التوصيات:</strong> ${policy.recommendations.length}</p>
|
| 1037 |
+
</div>
|
| 1038 |
+
`);
|
| 1039 |
+
}).catch(error => {
|
| 1040 |
+
showDemoResult('policy-generator', `
|
| 1041 |
+
<div class="warning-box">
|
| 1042 |
+
<p>خطأ في توليد السياسة: ${error.message}</p>
|
| 1043 |
+
</div>
|
| 1044 |
+
`);
|
| 1045 |
+
});
|
| 1046 |
+
}
|
| 1047 |
+
|
| 1048 |
+
function demoInteractiveTraining() {
|
| 1049 |
+
showDemoResult('interactive-training', `
|
| 1050 |
+
<div class="info-box">
|
| 1051 |
+
<h4>منصة التدريب التفاعلي</h4>
|
| 1052 |
+
<p>اختر الوحدة التي تريد تعلمها:</p>
|
| 1053 |
+
<div style="margin-top: 1rem;">
|
| 1054 |
+
<button class="btn btn-primary" onclick="startTrainingModule('fundamentals')">
|
| 1055 |
+
أساسيات أمان الويب
|
| 1056 |
+
</button>
|
| 1057 |
+
<button class="btn btn-primary" onclick="startTrainingModule('xss')">
|
| 1058 |
+
منع هجمات XSS
|
| 1059 |
+
</button>
|
| 1060 |
+
<button class="btn btn-primary" onclick="startTrainingModule('csrf')">
|
| 1061 |
+
حماية من CSRF
|
| 1062 |
+
</button>
|
| 1063 |
+
</div>
|
| 1064 |
+
</div>
|
| 1065 |
+
`);
|
| 1066 |
+
}
|
| 1067 |
+
|
| 1068 |
+
// وظائف لوحة المعلومات
|
| 1069 |
+
function switchDashboardView(view) {
|
| 1070 |
+
document.querySelectorAll('.control-btn').forEach(btn => {
|
| 1071 |
+
btn.classList.remove('active');
|
| 1072 |
+
});
|
| 1073 |
+
event.target.classList.add('active');
|
| 1074 |
+
|
| 1075 |
+
// تحديث البيانات حسب العرض المختار
|
| 1076 |
+
showNotification(`تم التبديل إلى عرض ${view}`, 'info');
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
// وظائف التدريب
|
| 1080 |
+
function startTrainingModule(moduleId) {
|
| 1081 |
+
if (!securityTraining) {
|
| 1082 |
+
securityTraining = new SecurityTraining();
|
| 1083 |
+
}
|
| 1084 |
+
|
| 1085 |
+
const moduleData = securityTraining.startModule(moduleId);
|
| 1086 |
+
if (moduleData) {
|
| 1087 |
+
showNotification(`بدء وحدة ${moduleData.module.title}`, 'success');
|
| 1088 |
+
// يمكن فتح نافذة جديدة أو تحديث المحتوى الحالي
|
| 1089 |
+
}
|
| 1090 |
+
}
|
| 1091 |
+
|
| 1092 |
+
function previewTrainingModule(moduleId) {
|
| 1093 |
+
showNotification(`معاينة وحدة ${moduleId}`, 'info');
|
| 1094 |
+
// عرض معاينة الوحدة
|
| 1095 |
+
}
|
| 1096 |
+
|
| 1097 |
+
// وظائف الأدوات
|
| 1098 |
+
function simulateXSSAttack() {
|
| 1099 |
+
const input = document.getElementById('xss-demo-input').value;
|
| 1100 |
+
const output = document.getElementById('xss-demo-output');
|
| 1101 |
+
|
| 1102 |
+
if (!input) {
|
| 1103 |
+
output.innerHTML = '<em>يرجى إدخال نص أولاً</em>';
|
| 1104 |
+
return;
|
| 1105 |
+
}
|
| 1106 |
+
|
| 1107 |
+
// محاكاة آمنة - لا يتم تنفيذ الكود
|
| 1108 |
+
const safeOutput = input
|
| 1109 |
+
.replace(/</g, '<')
|
| 1110 |
+
.replace(/>/g, '>')
|
| 1111 |
+
.replace(/"/g, '"')
|
| 1112 |
+
.replace(/'/g, ''');
|
| 1113 |
+
|
| 1114 |
+
output.innerHTML = `
|
| 1115 |
+
<div class="info-box">
|
| 1116 |
+
<h4>النتيجة الآمنة</h4>
|
| 1117 |
+
<p>تم عرض النص بأمان بدون تنفيذ الكود:</p>
|
| 1118 |
+
<code>${safeOutput}</code>
|
| 1119 |
+
<p style="margin-top: 1rem; color: #00C851;">
|
| 1120 |
+
<i class="fas fa-check-circle"></i> تم الحماية من XSS بنجاح!
|
| 1121 |
+
</p>
|
| 1122 |
+
</div>
|
| 1123 |
+
`;
|
| 1124 |
+
}
|
| 1125 |
+
|
| 1126 |
+
function generateCSP() {
|
| 1127 |
+
const template = document.getElementById('csp-template').value;
|
| 1128 |
+
const output = document.getElementById('csp-demo-output');
|
| 1129 |
+
|
| 1130 |
+
const policies = {
|
| 1131 |
+
basic: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;",
|
| 1132 |
+
strict: "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; frame-ancestors 'none';",
|
| 1133 |
+
modern: "default-src 'self'; script-src 'self' 'strict-dynamic'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; require-trusted-types-for 'script';",
|
| 1134 |
+
ecommerce: "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:;"
|
| 1135 |
+
};
|
| 1136 |
+
|
| 1137 |
+
output.innerHTML = policies[template] || policies.basic;
|
| 1138 |
+
}
|
| 1139 |
+
|
| 1140 |
+
function scanWebsite() {
|
| 1141 |
+
const url = document.getElementById('scan-demo-input').value;
|
| 1142 |
+
const output = document.getElementById('scan-demo-output');
|
| 1143 |
+
|
| 1144 |
+
if (!url) {
|
| 1145 |
+
output.innerHTML = '<em>يرجى إدخال رابط الموقع أولاً</em>';
|
| 1146 |
+
return;
|
| 1147 |
+
}
|
| 1148 |
+
|
| 1149 |
+
output.innerHTML = '<em>جاري فحص الموقع...</em>';
|
| 1150 |
+
|
| 1151 |
+
// محاكاة فحص الموقع
|
| 1152 |
+
setTimeout(() => {
|
| 1153 |
+
const mockResults = {
|
| 1154 |
+
csp: 'موجود',
|
| 1155 |
+
https: 'مفعل',
|
| 1156 |
+
xss: 'محمي',
|
| 1157 |
+
csrf: 'يحتاج تحسين',
|
| 1158 |
+
headers: 'جزئياً آمن'
|
| 1159 |
+
};
|
| 1160 |
+
|
| 1161 |
+
output.innerHTML = `
|
| 1162 |
+
<div class="success-box">
|
| 1163 |
+
<h4>نتائج الفحص</h4>
|
| 1164 |
+
<ul style="list-style: none; padding: 0;">
|
| 1165 |
+
${Object.entries(mockResults).map(([check, status]) => `
|
| 1166 |
+
<li style="margin: 0.5rem 0; padding: 0.5rem; background: rgba(0,0,0,0.2); border-radius: 4px;">
|
| 1167 |
+
<strong>${check.toUpperCase()}:</strong>
|
| 1168 |
+
<span style="color: ${status.includes('يحتاج') ? '#FFBB33' : '#00C851'}">
|
| 1169 |
+
${status}
|
| 1170 |
+
</span>
|
| 1171 |
+
</li>
|
| 1172 |
+
`).join('')}
|
| 1173 |
+
</ul>
|
| 1174 |
+
</div>
|
| 1175 |
+
`;
|
| 1176 |
+
}, 2000);
|
| 1177 |
+
}
|
| 1178 |
+
|
| 1179 |
+
// وظائف مساعدة
|
| 1180 |
+
function showDemoResult(containerId, content) {
|
| 1181 |
+
// يمكن تحسين هذا لعرض نتائج أكثر تفاعلاً
|
| 1182 |
+
console.log('Demo result for', containerId, ':', content);
|
| 1183 |
+
}
|
| 1184 |
+
|
| 1185 |
+
function showNotification(message, type = 'info') {
|
| 1186 |
+
// إنشاء إشعار
|
| 1187 |
+
const notification = document.createElement('div');
|
| 1188 |
+
notification.className = `notification notification-${type}`;
|
| 1189 |
+
notification.innerHTML = `
|
| 1190 |
+
<i class="fas fa-${getNotificationIcon(type)}"></i>
|
| 1191 |
+
<span>${message}</span>
|
| 1192 |
+
<button class="notification-close" onclick="this.parentElement.remove()">
|
| 1193 |
+
<i class="fas fa-times"></i>
|
| 1194 |
+
</button>
|
| 1195 |
+
`;
|
| 1196 |
+
|
| 1197 |
+
// إضافة الأنماط
|
| 1198 |
+
notification.style.cssText = `
|
| 1199 |
+
position: fixed;
|
| 1200 |
+
top: 20px;
|
| 1201 |
+
right: 20px;
|
| 1202 |
+
background: ${getNotificationColor(type)};
|
| 1203 |
+
color: white;
|
| 1204 |
+
padding: 1rem 1.5rem;
|
| 1205 |
+
border-radius: 8px;
|
| 1206 |
+
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
|
| 1207 |
+
z-index: 10000;
|
| 1208 |
+
display: flex;
|
| 1209 |
+
align-items: center;
|
| 1210 |
+
gap: 0.5rem;
|
| 1211 |
+
animation: slideIn 0.3s ease-out;
|
| 1212 |
+
`;
|
| 1213 |
+
|
| 1214 |
+
document.body.appendChild(notification);
|
| 1215 |
+
|
| 1216 |
+
// إزالة تلقائية بعد 5 ثوان
|
| 1217 |
+
setTimeout(() => {
|
| 1218 |
+
if (notification.parentElement) {
|
| 1219 |
+
notification.style.animation = 'slideOut 0.3s ease-out';
|
| 1220 |
+
setTimeout(() => notification.remove(), 300);
|
| 1221 |
+
}
|
| 1222 |
+
}, 5000);
|
| 1223 |
+
}
|
| 1224 |
+
|
| 1225 |
+
function getNotificationIcon(type) {
|
| 1226 |
+
const icons = {
|
| 1227 |
+
info: 'info-circle',
|
| 1228 |
+
success: 'check-circle',
|
| 1229 |
+
warning: 'exclamation-triangle',
|
| 1230 |
+
error: 'times-circle'
|
| 1231 |
+
};
|
| 1232 |
+
return icons[type] || 'info-circle';
|
| 1233 |
+
}
|
| 1234 |
+
|
| 1235 |
+
function getNotificationColor(type) {
|
| 1236 |
+
const colors = {
|
| 1237 |
+
info: '#00E0D5',
|
| 1238 |
+
success: '#00C851',
|
| 1239 |
+
warning: '#FFBB33',
|
| 1240 |
+
error: '#FF4444'
|
| 1241 |
+
};
|
| 1242 |
+
return colors[type] || '#00E0D5';
|
| 1243 |
+
}
|
| 1244 |
+
|
| 1245 |
+
// إضافة الأنيميشن
|
| 1246 |
+
const style = document.createElement('style');
|
| 1247 |
+
style.textContent = `
|
| 1248 |
+
@keyframes slideIn {
|
| 1249 |
+
from { transform: translateX(100%); opacity: 0; }
|
| 1250 |
+
to { transform: translateX(0); opacity: 1; }
|
| 1251 |
+
}
|
| 1252 |
+
@keyframes slideOut {
|
| 1253 |
+
from { transform: translateX(0); opacity: 1; }
|
| 1254 |
+
to { transform: translateX(100%); opacity: 0; }
|
| 1255 |
+
}
|
| 1256 |
+
`;
|
| 1257 |
+
document.head.appendChild(style);
|
| 1258 |
+
|
| 1259 |
+
// تشغيل تلقائي عند تحميل الصفحة
|
| 1260 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 1261 |
+
showNotification('مرحباً بك في منصة الأمان المتقدمة 2025!', 'success');
|
| 1262 |
+
});
|
| 1263 |
+
</script>
|
| 1264 |
+
</body>
|
| 1265 |
+
</html>
|
ar-controller.js
ADDED
|
@@ -0,0 +1,996 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* 📱 AR Controller - تحكم الواقع المعزز
|
| 3 |
+
* نظام متقدم للواقع المعزز لمركز القيادة الغامر
|
| 4 |
+
*
|
| 5 |
+
* المميزات:
|
| 6 |
+
* - كشف الأسطح التلقائي
|
| 7 |
+
* - وضع العناصر المجسمة
|
| 8 |
+
* - تتبع المواقع الجغرافية
|
| 9 |
+
* - دمج البيانات الحقيقية
|
| 10 |
+
* - دعم المحاكاة التعليمية
|
| 11 |
+
*
|
| 12 |
+
* @author MiniMax Agent
|
| 13 |
+
* @version 2025.12.10
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
class ARController {
|
| 17 |
+
constructor(scene, camera, renderer) {
|
| 18 |
+
this.scene = scene;
|
| 19 |
+
this.camera = camera;
|
| 20 |
+
this.renderer = renderer;
|
| 21 |
+
this.isInitialized = false;
|
| 22 |
+
this.isSessionActive = false;
|
| 23 |
+
this.session = null;
|
| 24 |
+
this.referenceSpace = null;
|
| 25 |
+
this.planes = new Map();
|
| 26 |
+
this.anchors = new Map();
|
| 27 |
+
this.trackedImages = new Map();
|
| 28 |
+
this.currentAnchor = null;
|
| 29 |
+
|
| 30 |
+
// إعدادات AR
|
| 31 |
+
this.config = {
|
| 32 |
+
sessionType: 'immersive-ar',
|
| 33 |
+
requiredFeatures: ['local'],
|
| 34 |
+
optionalFeatures: ['hit-test', 'dom-overlay', 'plane-detection', 'light-estimation'],
|
| 35 |
+
maxAnchors: 20,
|
| 36 |
+
planeDetection: true,
|
| 37 |
+
domOverlay: {
|
| 38 |
+
root: document.body
|
| 39 |
+
},
|
| 40 |
+
trackedImages: []
|
| 41 |
+
};
|
| 42 |
+
|
| 43 |
+
// بيانات الأسطح المحاكاة
|
| 44 |
+
this.mockPlanes = this.createMockPlanes();
|
| 45 |
+
|
| 46 |
+
// حالة النظام
|
| 47 |
+
this.systemState = {
|
| 48 |
+
lightIntensity: 0.8,
|
| 49 |
+
planeCount: 0,
|
| 50 |
+
anchorCount: 0,
|
| 51 |
+
isTracking: false
|
| 52 |
+
};
|
| 53 |
+
|
| 54 |
+
console.log('📱 تم تهيئة AR Controller');
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
/**
|
| 58 |
+
* تهيئة نظام AR
|
| 59 |
+
*/
|
| 60 |
+
async initialize() {
|
| 61 |
+
try {
|
| 62 |
+
console.log('🔧 بدء تهيئة AR...');
|
| 63 |
+
|
| 64 |
+
// فحص دعم WebXR
|
| 65 |
+
if (!navigator.xr) {
|
| 66 |
+
throw new Error('WebXR غير مدعوم في هذا المتصفح');
|
| 67 |
+
}
|
| 68 |
+
|
| 69 |
+
// فحص دعم AR
|
| 70 |
+
const isARAvailable = await navigator.xr.isSessionSupported(this.config.sessionType);
|
| 71 |
+
if (!isARAvailable) {
|
| 72 |
+
throw new Error('AR غير متاح على هذا الجهاز');
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
// تهيئة كشف الأسطح
|
| 76 |
+
if (this.config.planeDetection) {
|
| 77 |
+
await this.initializePlaneDetection();
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
// تهيئة تقدير الإضاءة
|
| 81 |
+
await this.initializeLightEstimation();
|
| 82 |
+
|
| 83 |
+
// تهيئة تتبع الصور (اختياري)
|
| 84 |
+
if (this.config.trackedImages.length > 0) {
|
| 85 |
+
await this.initializeImageTracking();
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
this.isInitialized = true;
|
| 89 |
+
console.log('✅ تم تهيئة AR بنجاح');
|
| 90 |
+
|
| 91 |
+
return true;
|
| 92 |
+
|
| 93 |
+
} catch (error) {
|
| 94 |
+
console.error('❌ خطأ في تهيئة AR:', error);
|
| 95 |
+
throw error;
|
| 96 |
+
}
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
/**
|
| 100 |
+
* تهيئة كشف الأسطح
|
| 101 |
+
*/
|
| 102 |
+
async initializePlaneDetection() {
|
| 103 |
+
console.log('🟦 تهيئة كشف الأسطح...');
|
| 104 |
+
|
| 105 |
+
// إنشاء نظام كشف أسطح وهمي
|
| 106 |
+
this.planeDetection = {
|
| 107 |
+
planes: new Map(),
|
| 108 |
+
onPlaneDetected: (plane) => {
|
| 109 |
+
this.handlePlaneDetected(plane);
|
| 110 |
+
},
|
| 111 |
+
onPlaneUpdated: (plane) => {
|
| 112 |
+
this.handlePlaneUpdated(plane);
|
| 113 |
+
},
|
| 114 |
+
onPlaneRemoved: (plane) => {
|
| 115 |
+
this.handlePlaneRemoved(plane);
|
| 116 |
+
}
|
| 117 |
+
};
|
| 118 |
+
|
| 119 |
+
console.log('✅ تم تهيئة كشف الأسطح');
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
/**
|
| 123 |
+
* تهيئة تقدير الإضاءة
|
| 124 |
+
*/
|
| 125 |
+
async initializeLightEstimation() {
|
| 126 |
+
console.log('💡 تهيئة تقدير الإضاءة...');
|
| 127 |
+
|
| 128 |
+
this.lightEstimation = {
|
| 129 |
+
isAvailable: true,
|
| 130 |
+
currentLight: {
|
| 131 |
+
primaryLightDirection: { x: 0.5, y: -1, z: 0.3 },
|
| 132 |
+
primaryLightIntensity: 0.8,
|
| 133 |
+
sphericalHarmonics: {
|
| 134 |
+
coefficients: Array(9).fill(0).map(() => Math.random() * 0.5)
|
| 135 |
+
}
|
| 136 |
+
},
|
| 137 |
+
update: (estimation) => {
|
| 138 |
+
this.handleLightEstimationUpdate(estimation);
|
| 139 |
+
}
|
| 140 |
+
};
|
| 141 |
+
|
| 142 |
+
console.log('✅ تم تهيئة تقدير الإضاءة');
|
| 143 |
+
}
|
| 144 |
+
|
| 145 |
+
/**
|
| 146 |
+
* تهيئة تتبع الصور
|
| 147 |
+
*/
|
| 148 |
+
async initializeImageTracking() {
|
| 149 |
+
console.log('🖼️ تهيئة تتبع الصور...');
|
| 150 |
+
|
| 151 |
+
// تحميل الصور للتتبع
|
| 152 |
+
for (const imageData of this.config.trackedImages) {
|
| 153 |
+
try {
|
| 154 |
+
const image = await this.loadImage(imageData.src);
|
| 155 |
+
this.trackedImages.set(imageData.id, {
|
| 156 |
+
image: image,
|
| 157 |
+
width: imageData.width,
|
| 158 |
+
tracked: false,
|
| 159 |
+
pose: null
|
| 160 |
+
});
|
| 161 |
+
} catch (error) {
|
| 162 |
+
console.warn(`تعذر تحميل صورة التتبع ${imageData.id}:`, error);
|
| 163 |
+
}
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
console.log('✅ تم تهيئة تتبع الصور');
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
/**
|
| 170 |
+
* تحميل صورة
|
| 171 |
+
*/
|
| 172 |
+
loadImage(src) {
|
| 173 |
+
return new Promise((resolve, reject) => {
|
| 174 |
+
const img = new Image();
|
| 175 |
+
img.crossOrigin = 'anonymous';
|
| 176 |
+
img.onload = () => resolve(img);
|
| 177 |
+
img.onerror = reject;
|
| 178 |
+
img.src = src;
|
| 179 |
+
});
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
/**
|
| 183 |
+
* بدء جلسة AR
|
| 184 |
+
*/
|
| 185 |
+
async startSession() {
|
| 186 |
+
if (!this.isInitialized) {
|
| 187 |
+
throw new Error('AR غير مهيأ بعد');
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
try {
|
| 191 |
+
console.log('🚀 بدء جلسة AR...');
|
| 192 |
+
|
| 193 |
+
// طلب جلسة AR
|
| 194 |
+
this.session = await navigator.xr.requestSession(this.config.sessionType, {
|
| 195 |
+
requiredFeatures: this.config.requiredFeatures,
|
| 196 |
+
optionalFeatures: this.config.optionalFeatures,
|
| 197 |
+
domOverlay: this.config.domOverlay
|
| 198 |
+
});
|
| 199 |
+
|
| 200 |
+
// ربط أحداث الجلسة
|
| 201 |
+
this.bindSessionEvents();
|
| 202 |
+
|
| 203 |
+
// بدء تقديم المشهد
|
| 204 |
+
this.renderer.xr.enabled = true;
|
| 205 |
+
this.renderer.xr.setReferenceSpaceType('local');
|
| 206 |
+
await this.renderer.xr.setSession(this.session);
|
| 207 |
+
|
| 208 |
+
this.isSessionActive = true;
|
| 209 |
+
this.startSessionLoop();
|
| 210 |
+
|
| 211 |
+
console.log('✅ تم بدء جلسة AR بنجاح');
|
| 212 |
+
this.emit('session_start');
|
| 213 |
+
|
| 214 |
+
} catch (error) {
|
| 215 |
+
console.error('❌ خطأ في بدء جلسة AR:', error);
|
| 216 |
+
throw error;
|
| 217 |
+
}
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
/**
|
| 221 |
+
* إنهاء جلسة AR
|
| 222 |
+
*/
|
| 223 |
+
async endSession() {
|
| 224 |
+
if (!this.session || !this.isSessionActive) {
|
| 225 |
+
return;
|
| 226 |
+
}
|
| 227 |
+
|
| 228 |
+
try {
|
| 229 |
+
console.log('🛑 إنهاء جلسة AR...');
|
| 230 |
+
|
| 231 |
+
this.isSessionActive = false;
|
| 232 |
+
|
| 233 |
+
if (this.session) {
|
| 234 |
+
await this.session.end();
|
| 235 |
+
this.session = null;
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
// إيقاف تقديم المشهد
|
| 239 |
+
this.renderer.xr.enabled = false;
|
| 240 |
+
|
| 241 |
+
// تنظيف المراسي والأسطح
|
| 242 |
+
this.cleanupAnchors();
|
| 243 |
+
this.cleanupPlanes();
|
| 244 |
+
|
| 245 |
+
console.log('✅ تم إنهاء جلسة AR');
|
| 246 |
+
this.emit('session_end');
|
| 247 |
+
|
| 248 |
+
} catch (error) {
|
| 249 |
+
console.error('❌ خطأ في إنهاء جلسة AR:', error);
|
| 250 |
+
}
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
/**
|
| 254 |
+
* ربط أحداث الجلسة
|
| 255 |
+
*/
|
| 256 |
+
bindSessionEvents() {
|
| 257 |
+
this.session.addEventListener('end', () => {
|
| 258 |
+
this.isSessionActive = false;
|
| 259 |
+
this.emit('session_end');
|
| 260 |
+
});
|
| 261 |
+
|
| 262 |
+
this.session.addEventListener('inputsourceschange', (event) => {
|
| 263 |
+
this.handleInputSourcesChange(event);
|
| 264 |
+
});
|
| 265 |
+
|
| 266 |
+
this.session.addEventListener('select', (event) => {
|
| 267 |
+
this.handleSelect(event);
|
| 268 |
+
});
|
| 269 |
+
}
|
| 270 |
+
|
| 271 |
+
/**
|
| 272 |
+
* معالجة تغيير مصادر الإدخال
|
| 273 |
+
*/
|
| 274 |
+
handleInputSourcesChange(event) {
|
| 275 |
+
const { added, removed } = event;
|
| 276 |
+
|
| 277 |
+
added.forEach(inputSource => {
|
| 278 |
+
console.log('➕ إضافة مصدر إدخال AR:', inputSource.handedness);
|
| 279 |
+
});
|
| 280 |
+
|
| 281 |
+
removed.forEach(inputSource => {
|
| 282 |
+
console.log('➖ إزالة مصدر إدخال AR:', inputSource.handedness);
|
| 283 |
+
});
|
| 284 |
+
}
|
| 285 |
+
|
| 286 |
+
/**
|
| 287 |
+
* معالجة الاختيار
|
| 288 |
+
*/
|
| 289 |
+
handleSelect(event) {
|
| 290 |
+
console.log('👆 حدث اختيار في AR');
|
| 291 |
+
|
| 292 |
+
// تنفيذ hit test
|
| 293 |
+
this.performHitTest(event);
|
| 294 |
+
}
|
| 295 |
+
|
| 296 |
+
/**
|
| 297 |
+
* إجراء hit test
|
| 298 |
+
*/
|
| 299 |
+
async performHitTest(event) {
|
| 300 |
+
try {
|
| 301 |
+
// محاكاة hit test
|
| 302 |
+
const hitTestResults = await this.simulateHitTest(event);
|
| 303 |
+
|
| 304 |
+
if (hitTestResults.length > 0) {
|
| 305 |
+
const hit = hitTestResults[0];
|
| 306 |
+
console.log('🎯 hit test نجح:', hit);
|
| 307 |
+
|
| 308 |
+
// إنشاء مرساة في الموقع المحدد
|
| 309 |
+
await this.createAnchor(hit.position, hit.rotation);
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
} catch (error) {
|
| 313 |
+
console.warn('خطأ في hit test:', error);
|
| 314 |
+
}
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
/**
|
| 318 |
+
* محاكاة hit test
|
| 319 |
+
*/
|
| 320 |
+
simulateHitTest(event) {
|
| 321 |
+
return new Promise((resolve) => {
|
| 322 |
+
// محاكاة نتائج hit test
|
| 323 |
+
const results = [];
|
| 324 |
+
|
| 325 |
+
// فحص الأسطح المتاحة
|
| 326 |
+
const availablePlanes = Array.from(this.planes.values());
|
| 327 |
+
|
| 328 |
+
if (availablePlanes.length > 0) {
|
| 329 |
+
const plane = availablePlanes[0];
|
| 330 |
+
|
| 331 |
+
// إنشاء نتيجة hit test وهمية
|
| 332 |
+
const result = {
|
| 333 |
+
position: {
|
| 334 |
+
x: plane.center.x + (Math.random() - 0.5) * plane.width,
|
| 335 |
+
y: plane.center.y,
|
| 336 |
+
z: plane.center.z + (Math.random() - 0.5) * plane.depth
|
| 337 |
+
},
|
| 338 |
+
rotation: { x: 0, y: 0, z: 0, w: 1 },
|
| 339 |
+
plane: plane
|
| 340 |
+
};
|
| 341 |
+
|
| 342 |
+
results.push(result);
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
// إرجاع النتائج بعد تأخير قصير
|
| 346 |
+
setTimeout(() => resolve(results), 100);
|
| 347 |
+
});
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
/**
|
| 351 |
+
* إنشاء مرساة
|
| 352 |
+
*/
|
| 353 |
+
async createAnchor(position, rotation) {
|
| 354 |
+
try {
|
| 355 |
+
const anchorId = `anchor_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
| 356 |
+
|
| 357 |
+
// إنشاء كائن ثلاثي الأبعاد للمرساة
|
| 358 |
+
const anchorMesh = this.createAnchorMesh();
|
| 359 |
+
anchorMesh.position.set(position.x, position.y, position.z);
|
| 360 |
+
|
| 361 |
+
if (rotation) {
|
| 362 |
+
anchorMesh.quaternion.set(rotation.x, rotation.y, rotation.z, rotation.w);
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
this.scene.add(anchorMesh);
|
| 366 |
+
|
| 367 |
+
// حفظ المرساة
|
| 368 |
+
const anchor = {
|
| 369 |
+
id: anchorId,
|
| 370 |
+
position: position,
|
| 371 |
+
rotation: rotation,
|
| 372 |
+
mesh: anchorMesh,
|
| 373 |
+
objects: [],
|
| 374 |
+
createdAt: new Date()
|
| 375 |
+
};
|
| 376 |
+
|
| 377 |
+
this.anchors.set(anchorId, anchor);
|
| 378 |
+
this.systemState.anchorCount = this.anchors.size;
|
| 379 |
+
|
| 380 |
+
console.log('📌 تم إنشاء مرساة:', anchorId);
|
| 381 |
+
this.emit('anchor_created', anchor);
|
| 382 |
+
|
| 383 |
+
return anchor;
|
| 384 |
+
|
| 385 |
+
} catch (error) {
|
| 386 |
+
console.error('خطأ في إنشاء المرساة:', error);
|
| 387 |
+
throw error;
|
| 388 |
+
}
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
/**
|
| 392 |
+
* إنشاء شكل المرساة ثلاثي الأبعاد
|
| 393 |
+
*/
|
| 394 |
+
createAnchorMesh() {
|
| 395 |
+
// إنشاء حلقة مرساة
|
| 396 |
+
const torusGeometry = new THREE.TorusGeometry(0.1, 0.02, 8, 16);
|
| 397 |
+
const torusMaterial = new THREE.MeshBasicMaterial({
|
| 398 |
+
color: 0x22d3ee,
|
| 399 |
+
transparent: true,
|
| 400 |
+
opacity: 0.8
|
| 401 |
+
});
|
| 402 |
+
|
| 403 |
+
const torus = new THREE.Mesh(torusGeometry, torusMaterial);
|
| 404 |
+
torus.rotation.x = Math.PI / 2;
|
| 405 |
+
|
| 406 |
+
// إضافة نقطة مركزية
|
| 407 |
+
const centerGeometry = new THREE.SphereGeometry(0.02, 8, 8);
|
| 408 |
+
const centerMaterial = new THREE.MeshBasicMaterial({
|
| 409 |
+
color: 0x22d3ee,
|
| 410 |
+
emissive: 0x22d3ee,
|
| 411 |
+
emissiveIntensity: 0.3
|
| 412 |
+
});
|
| 413 |
+
|
| 414 |
+
const center = new THREE.Mesh(centerGeometry, centerMaterial);
|
| 415 |
+
torus.add(center);
|
| 416 |
+
|
| 417 |
+
// إضافة أنيميشن نبضة
|
| 418 |
+
const animate = () => {
|
| 419 |
+
torus.scale.setScalar(1 + Math.sin(Date.now() * 0.005) * 0.1);
|
| 420 |
+
requestAnimationFrame(animate);
|
| 421 |
+
};
|
| 422 |
+
animate();
|
| 423 |
+
|
| 424 |
+
return torus;
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
/**
|
| 428 |
+
* وضع عنصر على المرساة
|
| 429 |
+
*/
|
| 430 |
+
placeObjectOnAnchor(anchorId, objectType, data = {}) {
|
| 431 |
+
const anchor = this.anchors.get(anchorId);
|
| 432 |
+
if (!anchor) {
|
| 433 |
+
throw new Error(`المرساة ${anchorId} غير موجودة`);
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
try {
|
| 437 |
+
// إنشاء الكائن ثلاثي الأبعاد
|
| 438 |
+
const object = this.createObject3D(objectType, data);
|
| 439 |
+
|
| 440 |
+
// وضع الكائن على المرساة
|
| 441 |
+
object.position.set(0, 0, 0);
|
| 442 |
+
anchor.mesh.add(object);
|
| 443 |
+
|
| 444 |
+
// حفظ الكائن في المرساة
|
| 445 |
+
anchor.objects.push({
|
| 446 |
+
id: `object_${Date.now()}`,
|
| 447 |
+
type: objectType,
|
| 448 |
+
mesh: object,
|
| 449 |
+
data: data,
|
| 450 |
+
createdAt: new Date()
|
| 451 |
+
});
|
| 452 |
+
|
| 453 |
+
console.log('📦 تم وضع كائن على المرساة:', objectType);
|
| 454 |
+
this.emit('object_placed', { anchor, object });
|
| 455 |
+
|
| 456 |
+
return object;
|
| 457 |
+
|
| 458 |
+
} catch (error) {
|
| 459 |
+
console.error('خطأ في وضع الكائن:', error);
|
| 460 |
+
throw error;
|
| 461 |
+
}
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
/**
|
| 465 |
+
* إنشاء كائن ثلاثي الأبعاد
|
| 466 |
+
*/
|
| 467 |
+
createObject3D(type, data) {
|
| 468 |
+
let geometry, material, mesh;
|
| 469 |
+
|
| 470 |
+
switch (type) {
|
| 471 |
+
case 'threat':
|
| 472 |
+
geometry = this.createThreatGeometry(data.threatType || 'XSS');
|
| 473 |
+
material = new THREE.MeshBasicMaterial({
|
| 474 |
+
color: this.getThreatColor(data.severity),
|
| 475 |
+
transparent: true,
|
| 476 |
+
opacity: 0.8
|
| 477 |
+
});
|
| 478 |
+
mesh = new THREE.Mesh(geometry, material);
|
| 479 |
+
break;
|
| 480 |
+
|
| 481 |
+
case 'network_node':
|
| 482 |
+
geometry = new THREE.SphereGeometry(0.05, 16, 16);
|
| 483 |
+
material = new THREE.MeshBasicMaterial({
|
| 484 |
+
color: 0x22d3ee,
|
| 485 |
+
transparent: true,
|
| 486 |
+
opacity: 0.9
|
| 487 |
+
});
|
| 488 |
+
mesh = new THREE.Mesh(geometry, material);
|
| 489 |
+
break;
|
| 490 |
+
|
| 491 |
+
case 'info_panel':
|
| 492 |
+
geometry = new THREE.PlaneGeometry(0.3, 0.2);
|
| 493 |
+
material = new THREE.MeshBasicMaterial({
|
| 494 |
+
color: 0x000000,
|
| 495 |
+
transparent: true,
|
| 496 |
+
opacity: 0.8,
|
| 497 |
+
side: THREE.DoubleSide
|
| 498 |
+
});
|
| 499 |
+
mesh = new THREE.Mesh(geometry, material);
|
| 500 |
+
|
| 501 |
+
// إضافة نص
|
| 502 |
+
const canvas = document.createElement('canvas');
|
| 503 |
+
canvas.width = 256;
|
| 504 |
+
canvas.height = 128;
|
| 505 |
+
const ctx = canvas.getContext('2d');
|
| 506 |
+
|
| 507 |
+
ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
|
| 508 |
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
| 509 |
+
|
| 510 |
+
ctx.fillStyle = '#22d3ee';
|
| 511 |
+
ctx.font = '16px Arial';
|
| 512 |
+
ctx.textAlign = 'center';
|
| 513 |
+
ctx.fillText(data.title || 'معلومات', canvas.width / 2, 40);
|
| 514 |
+
|
| 515 |
+
ctx.fillStyle = '#f0f2f5';
|
| 516 |
+
ctx.font = '12px Arial';
|
| 517 |
+
ctx.fillText(data.description || 'وصف المعلومات', canvas.width / 2, 80);
|
| 518 |
+
|
| 519 |
+
const texture = new THREE.CanvasTexture(canvas);
|
| 520 |
+
material.map = texture;
|
| 521 |
+
break;
|
| 522 |
+
|
| 523 |
+
default:
|
| 524 |
+
geometry = new THREE.BoxGeometry(0.1, 0.1, 0.1);
|
| 525 |
+
material = new THREE.MeshBasicMaterial({ color: 0x22d3ee });
|
| 526 |
+
mesh = new THREE.Mesh(geometry, material);
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
// إضافة بيانات المستخدم
|
| 530 |
+
mesh.userData = {
|
| 531 |
+
type: type,
|
| 532 |
+
data: data,
|
| 533 |
+
createdAt: new Date()
|
| 534 |
+
};
|
| 535 |
+
|
| 536 |
+
return mesh;
|
| 537 |
+
}
|
| 538 |
+
|
| 539 |
+
/**
|
| 540 |
+
* إنشاء شكل التهديد
|
| 541 |
+
*/
|
| 542 |
+
createThreatGeometry(threatType) {
|
| 543 |
+
switch (threatType) {
|
| 544 |
+
case 'XSS':
|
| 545 |
+
return new THREE.SphereGeometry(0.05, 16, 16);
|
| 546 |
+
case 'SQL Injection':
|
| 547 |
+
return new THREE.BoxGeometry(0.08, 0.08, 0.08);
|
| 548 |
+
case 'Malware':
|
| 549 |
+
return new THREE.TetrahedronGeometry(0.07);
|
| 550 |
+
case 'DDoS':
|
| 551 |
+
return new THREE.OctahedronGeometry(0.06);
|
| 552 |
+
case 'Phishing':
|
| 553 |
+
return new THREE.ConeGeometry(0.05, 0.1, 8);
|
| 554 |
+
case 'Ransomware':
|
| 555 |
+
return new THREE.TorusGeometry(0.05, 0.02, 8, 16);
|
| 556 |
+
default:
|
| 557 |
+
return new THREE.IcosahedronGeometry(0.05);
|
| 558 |
+
}
|
| 559 |
+
}
|
| 560 |
+
|
| 561 |
+
/**
|
| 562 |
+
* الحصول على لون التهديد
|
| 563 |
+
*/
|
| 564 |
+
getThreatColor(severity) {
|
| 565 |
+
switch (severity) {
|
| 566 |
+
case 'منخفض':
|
| 567 |
+
return 0x34d399;
|
| 568 |
+
case 'متوسط':
|
| 569 |
+
return 0xfbbf24;
|
| 570 |
+
case 'عالي':
|
| 571 |
+
return 0xf97316;
|
| 572 |
+
case 'حرج':
|
| 573 |
+
return 0xf87171;
|
| 574 |
+
default:
|
| 575 |
+
return 0x22d3ee;
|
| 576 |
+
}
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
/**
|
| 580 |
+
* معالجة اكتشاف سطح
|
| 581 |
+
*/
|
| 582 |
+
handlePlaneDetected(plane) {
|
| 583 |
+
console.log('🟦 تم اكتشاف سطح جديد');
|
| 584 |
+
|
| 585 |
+
// إنشاء شكل السطح
|
| 586 |
+
const planeMesh = this.createPlaneMesh(plane);
|
| 587 |
+
|
| 588 |
+
// حفظ السطح
|
| 589 |
+
this.planes.set(plane.id, {
|
| 590 |
+
id: plane.id,
|
| 591 |
+
center: plane.center,
|
| 592 |
+
width: plane.width,
|
| 593 |
+
height: plane.height,
|
| 594 |
+
orientation: plane.orientation,
|
| 595 |
+
mesh: planeMesh,
|
| 596 |
+
createdAt: new Date()
|
| 597 |
+
});
|
| 598 |
+
|
| 599 |
+
this.systemState.planeCount = this.planes.size;
|
| 600 |
+
|
| 601 |
+
// إضافة للمشهد
|
| 602 |
+
this.scene.add(planeMesh);
|
| 603 |
+
|
| 604 |
+
this.emit('plane_detected', plane);
|
| 605 |
+
}
|
| 606 |
+
|
| 607 |
+
/**
|
| 608 |
+
* معالجة تحديث سطح
|
| 609 |
+
*/
|
| 610 |
+
handlePlaneUpdated(plane) {
|
| 611 |
+
const trackedPlane = this.planes.get(plane.id);
|
| 612 |
+
if (trackedPlane) {
|
| 613 |
+
// تحديث الموقع والأبعاد
|
| 614 |
+
trackedPlane.center = plane.center;
|
| 615 |
+
trackedPlane.width = plane.width;
|
| 616 |
+
trackedPlane.height = plane.height;
|
| 617 |
+
|
| 618 |
+
// تحديث الش��كة ثلاثية الأبعاد
|
| 619 |
+
trackedPlane.mesh.position.set(plane.center.x, plane.center.y, plane.center.z);
|
| 620 |
+
trackedPlane.mesh.rotation.setFromQuaternion(plane.orientation);
|
| 621 |
+
|
| 622 |
+
// تحديث الأبعاد
|
| 623 |
+
trackedPlane.mesh.scale.set(plane.width, 1, plane.height);
|
| 624 |
+
}
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
/**
|
| 628 |
+
* معالجة إزالة سطح
|
| 629 |
+
*/
|
| 630 |
+
handlePlaneRemoved(plane) {
|
| 631 |
+
const trackedPlane = this.planes.get(plane.id);
|
| 632 |
+
if (trackedPlane) {
|
| 633 |
+
this.scene.remove(trackedPlane.mesh);
|
| 634 |
+
this.planes.delete(plane.id);
|
| 635 |
+
this.systemState.planeCount = this.planes.size;
|
| 636 |
+
}
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
/**
|
| 640 |
+
* إنشاء شكل السطح
|
| 641 |
+
*/
|
| 642 |
+
createPlaneMesh(plane) {
|
| 643 |
+
const geometry = new THREE.PlaneGeometry(1, 1);
|
| 644 |
+
const material = new THREE.MeshBasicMaterial({
|
| 645 |
+
color: 0x22d3ee,
|
| 646 |
+
transparent: true,
|
| 647 |
+
opacity: 0.1,
|
| 648 |
+
side: THREE.DoubleSide
|
| 649 |
+
});
|
| 650 |
+
|
| 651 |
+
const mesh = new THREE.Mesh(geometry, material);
|
| 652 |
+
|
| 653 |
+
// تحديد الموقع والتوجيه
|
| 654 |
+
mesh.position.set(plane.center.x, plane.center.y, plane.center.z);
|
| 655 |
+
mesh.quaternion.set(plane.orientation.x, plane.orientation.y, plane.orientation.z, plane.orientation.w);
|
| 656 |
+
mesh.scale.set(plane.width, 1, plane.height);
|
| 657 |
+
|
| 658 |
+
// إضافة شبكة للتوضيح
|
| 659 |
+
const gridHelper = new THREE.GridHelper(plane.width, 10, 0x22d3ee, 0x22d3ee);
|
| 660 |
+
gridHelper.position.y = 0.001;
|
| 661 |
+
mesh.add(gridHelper);
|
| 662 |
+
|
| 663 |
+
return mesh;
|
| 664 |
+
}
|
| 665 |
+
|
| 666 |
+
/**
|
| 667 |
+
* إنشاء أسطح وهمية للاختبار
|
| 668 |
+
*/
|
| 669 |
+
createMockPlanes() {
|
| 670 |
+
return [
|
| 671 |
+
{
|
| 672 |
+
id: 'mock_plane_1',
|
| 673 |
+
center: { x: 0, y: 0, z: -1 },
|
| 674 |
+
width: 1,
|
| 675 |
+
height: 0.8,
|
| 676 |
+
orientation: { x: 0, y: 0, z: 0, w: 1 }
|
| 677 |
+
}
|
| 678 |
+
];
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
/**
|
| 682 |
+
* معالجة تحديث تقدير الإضاءة
|
| 683 |
+
*/
|
| 684 |
+
handleLightEstimationUpdate(estimation) {
|
| 685 |
+
if (estimation) {
|
| 686 |
+
this.systemState.lightIntensity = estimation.primaryLightIntensity || 0.8;
|
| 687 |
+
|
| 688 |
+
// تحديث إضاءة المشهد
|
| 689 |
+
this.updateSceneLighting(estimation);
|
| 690 |
+
|
| 691 |
+
console.log('💡 تم تحديث تقدير الإضاءة:', this.systemState.lightIntensity);
|
| 692 |
+
}
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
/**
|
| 696 |
+
* تحديث إضاءة المشهد
|
| 697 |
+
*/
|
| 698 |
+
updateSceneLighting(lightEstimation) {
|
| 699 |
+
// العثور على الإضاءة الرئيسية في المشهد
|
| 700 |
+
const directionalLight = this.scene.children.find(child =>
|
| 701 |
+
child.isDirectionalLight && child.userData.isMainLight
|
| 702 |
+
);
|
| 703 |
+
|
| 704 |
+
if (directionalLight) {
|
| 705 |
+
// تحديث اتجاه الإضاءة
|
| 706 |
+
if (lightEstimation.primaryLightDirection) {
|
| 707 |
+
const dir = lightEstimation.primaryLightDirection;
|
| 708 |
+
directionalLight.position.set(dir.x * 10, dir.y * 10, dir.z * 10);
|
| 709 |
+
}
|
| 710 |
+
|
| 711 |
+
// تحديث شدة الإضاءة
|
| 712 |
+
if (lightEstimation.primaryLightIntensity) {
|
| 713 |
+
directionalLight.intensity = lightEstimation.primaryLightIntensity;
|
| 714 |
+
}
|
| 715 |
+
}
|
| 716 |
+
}
|
| 717 |
+
|
| 718 |
+
/**
|
| 719 |
+
* بدء حلقة الجلسة
|
| 720 |
+
*/
|
| 721 |
+
startSessionLoop() {
|
| 722 |
+
const animate = () => {
|
| 723 |
+
if (!this.isSessionActive) return;
|
| 724 |
+
|
| 725 |
+
// تحديث الأسطح
|
| 726 |
+
this.updatePlanes();
|
| 727 |
+
|
| 728 |
+
// تحديث المراسي
|
| 729 |
+
this.updateAnchors();
|
| 730 |
+
|
| 731 |
+
// تحديث تتبع الصور
|
| 732 |
+
this.updateImageTracking();
|
| 733 |
+
|
| 734 |
+
// تحديث تقدير الإضاءة
|
| 735 |
+
this.updateLightEstimation();
|
| 736 |
+
|
| 737 |
+
// طلب الإطار التالي
|
| 738 |
+
this.session.requestAnimationFrame(animate);
|
| 739 |
+
};
|
| 740 |
+
|
| 741 |
+
this.session.requestAnimationFrame(animate);
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
/**
|
| 745 |
+
* تحديث الأسطح
|
| 746 |
+
*/
|
| 747 |
+
updatePlanes() {
|
| 748 |
+
// محاكاة تحديث الأسطح المكتشفة
|
| 749 |
+
if (this.mockPlanes.length > 0) {
|
| 750 |
+
this.mockPlanes.forEach(mockPlane => {
|
| 751 |
+
// فحص ما إذا كان السطح موجود بالفعل
|
| 752 |
+
let plane = this.planes.get(mockPlane.id);
|
| 753 |
+
if (!plane) {
|
| 754 |
+
// إنشاء سطح جديد
|
| 755 |
+
this.handlePlaneDetected(mockPlane);
|
| 756 |
+
} else {
|
| 757 |
+
// تحديث السطح الموجود
|
| 758 |
+
this.handlePlaneUpdated(mockPlane);
|
| 759 |
+
}
|
| 760 |
+
});
|
| 761 |
+
}
|
| 762 |
+
}
|
| 763 |
+
|
| 764 |
+
/**
|
| 765 |
+
* تحديث المراسي
|
| 766 |
+
*/
|
| 767 |
+
updateAnchors() {
|
| 768 |
+
this.anchors.forEach(anchor => {
|
| 769 |
+
// تحديث المرساة بناءً على موقعها
|
| 770 |
+
if (anchor.mesh) {
|
| 771 |
+
// إضافة دوران بطيء للمرساة
|
| 772 |
+
anchor.mesh.rotation.y += 0.01;
|
| 773 |
+
|
| 774 |
+
// تحديث حالة الرؤية
|
| 775 |
+
const distanceFromCamera = this.camera.position.distanceTo(anchor.mesh.position);
|
| 776 |
+
anchor.mesh.visible = distanceFromCamera < 5; // إخفاء المرساة إذا كانت بعيدة جداً
|
| 777 |
+
}
|
| 778 |
+
});
|
| 779 |
+
}
|
| 780 |
+
|
| 781 |
+
/**
|
| 782 |
+
* تحديث تتبع الصور
|
| 783 |
+
*/
|
| 784 |
+
updateImageTracking() {
|
| 785 |
+
this.trackedImages.forEach((imageData, id) => {
|
| 786 |
+
// محاكاة تتبع الصور
|
| 787 |
+
if (Math.random() > 0.95) { // 5% احتمال تتبع الصورة
|
| 788 |
+
if (!imageData.tracked) {
|
| 789 |
+
imageData.tracked = true;
|
| 790 |
+
imageData.pose = this.generateRandomPose();
|
| 791 |
+
console.log('🖼️ تم تتبع صورة:', id);
|
| 792 |
+
this.emit('image_tracked', { id, pose: imageData.pose });
|
| 793 |
+
}
|
| 794 |
+
} else {
|
| 795 |
+
imageData.tracked = false;
|
| 796 |
+
}
|
| 797 |
+
});
|
| 798 |
+
}
|
| 799 |
+
|
| 800 |
+
/**
|
| 801 |
+
* توليد وضعية عشوائية
|
| 802 |
+
*/
|
| 803 |
+
generateRandomPose() {
|
| 804 |
+
return {
|
| 805 |
+
position: {
|
| 806 |
+
x: (Math.random() - 0.5) * 2,
|
| 807 |
+
y: Math.random() * 2,
|
| 808 |
+
z: (Math.random() - 0.5) * 2
|
| 809 |
+
},
|
| 810 |
+
rotation: {
|
| 811 |
+
x: 0,
|
| 812 |
+
y: (Math.random() - 0.5) * Math.PI * 2,
|
| 813 |
+
z: 0,
|
| 814 |
+
w: 1
|
| 815 |
+
}
|
| 816 |
+
};
|
| 817 |
+
}
|
| 818 |
+
|
| 819 |
+
/**
|
| 820 |
+
* تحديث تقدير الإضاءة
|
| 821 |
+
*/
|
| 822 |
+
updateLightEstimation() {
|
| 823 |
+
// محاكاة تغييرات الإضاءة
|
| 824 |
+
const time = Date.now() * 0.001;
|
| 825 |
+
this.systemState.lightIntensity = 0.7 + Math.sin(time * 0.5) * 0.3;
|
| 826 |
+
|
| 827 |
+
if (this.lightEstimation) {
|
| 828 |
+
this.lightEstimation.currentLight.primaryLightIntensity = this.systemState.lightIntensity;
|
| 829 |
+
}
|
| 830 |
+
}
|
| 831 |
+
|
| 832 |
+
/**
|
| 833 |
+
* تنظيف المراسي
|
| 834 |
+
*/
|
| 835 |
+
cleanupAnchors() {
|
| 836 |
+
this.anchors.forEach(anchor => {
|
| 837 |
+
if (anchor.mesh) {
|
| 838 |
+
this.scene.remove(anchor.mesh);
|
| 839 |
+
}
|
| 840 |
+
});
|
| 841 |
+
this.anchors.clear();
|
| 842 |
+
this.systemState.anchorCount = 0;
|
| 843 |
+
}
|
| 844 |
+
|
| 845 |
+
/**
|
| 846 |
+
* تنظيف الأسطح
|
| 847 |
+
*/
|
| 848 |
+
cleanupPlanes() {
|
| 849 |
+
this.planes.forEach(plane => {
|
| 850 |
+
if (plane.mesh) {
|
| 851 |
+
this.scene.remove(plane.mesh);
|
| 852 |
+
}
|
| 853 |
+
});
|
| 854 |
+
this.planes.clear();
|
| 855 |
+
this.systemState.planeCount = 0;
|
| 856 |
+
}
|
| 857 |
+
|
| 858 |
+
/**
|
| 859 |
+
* الحصول على حالة النظام
|
| 860 |
+
*/
|
| 861 |
+
getSystemState() {
|
| 862 |
+
return {
|
| 863 |
+
...this.systemState,
|
| 864 |
+
isSessionActive: this.isSessionActive,
|
| 865 |
+
planes: Array.from(this.planes.values()).map(plane => ({
|
| 866 |
+
id: plane.id,
|
| 867 |
+
center: plane.center,
|
| 868 |
+
width: plane.width,
|
| 869 |
+
height: plane.height
|
| 870 |
+
})),
|
| 871 |
+
anchors: Array.from(this.anchors.values()).map(anchor => ({
|
| 872 |
+
id: anchor.id,
|
| 873 |
+
position: anchor.position,
|
| 874 |
+
objectCount: anchor.objects.length
|
| 875 |
+
}))
|
| 876 |
+
};
|
| 877 |
+
}
|
| 878 |
+
|
| 879 |
+
/**
|
| 880 |
+
* عرض تهديد في الواقع المعزز
|
| 881 |
+
*/
|
| 882 |
+
displayThreatInAR(threat, position) {
|
| 883 |
+
if (!this.isSessionActive) {
|
| 884 |
+
throw new Error('جلسة AR غير نشطة');
|
| 885 |
+
}
|
| 886 |
+
|
| 887 |
+
// إنشاء مرساة للتهديد
|
| 888 |
+
this.createAnchor(position, { x: 0, y: 0, z: 0, w: 1 })
|
| 889 |
+
.then(anchor => {
|
| 890 |
+
// وضع التهديد على المرساة
|
| 891 |
+
this.placeObjectOnAnchor(anchor.id, 'threat', {
|
| 892 |
+
threatType: threat.type,
|
| 893 |
+
severity: threat.severity,
|
| 894 |
+
description: threat.description
|
| 895 |
+
});
|
| 896 |
+
|
| 897 |
+
console.log('⚠️ تم عرض تهديد في AR:', threat.type);
|
| 898 |
+
})
|
| 899 |
+
.catch(error => {
|
| 900 |
+
console.error('خطأ في عرض التهديد في AR:', error);
|
| 901 |
+
});
|
| 902 |
+
}
|
| 903 |
+
|
| 904 |
+
/**
|
| 905 |
+
* عرض خريطة شبكة في الواقع المعزز
|
| 906 |
+
*/
|
| 907 |
+
displayNetworkMapInAR(networkData, centerPosition) {
|
| 908 |
+
if (!this.isSessionActive) {
|
| 909 |
+
throw new Error('جلسة AR غير نشطة');
|
| 910 |
+
}
|
| 911 |
+
|
| 912 |
+
// إنشاء مرساة للخريطة
|
| 913 |
+
this.createAnchor(centerPosition, { x: 0, y: 0, z: 0, w: 1 })
|
| 914 |
+
.then(anchor => {
|
| 915 |
+
// إضافة عقد الشبكة
|
| 916 |
+
networkData.nodes.forEach((node, index) => {
|
| 917 |
+
const nodePosition = {
|
| 918 |
+
x: (index % 5) * 0.3 - 0.6,
|
| 919 |
+
y: 0,
|
| 920 |
+
z: Math.floor(index / 5) * 0.3 - 0.6
|
| 921 |
+
};
|
| 922 |
+
|
| 923 |
+
this.placeObjectOnAnchor(anchor.id, 'network_node', {
|
| 924 |
+
zone: node.zone,
|
| 925 |
+
status: node.status,
|
| 926 |
+
connections: node.connections
|
| 927 |
+
});
|
| 928 |
+
});
|
| 929 |
+
|
| 930 |
+
// إضافة لوحة معلومات
|
| 931 |
+
this.placeObjectOnAnchor(anchor.id, 'info_panel', {
|
| 932 |
+
title: 'خريطة الشبكة',
|
| 933 |
+
description: `${networkData.nodes.length} عقدة نشطة`
|
| 934 |
+
});
|
| 935 |
+
|
| 936 |
+
console.log('🌐 تم عرض خريطة شبكة في AR');
|
| 937 |
+
})
|
| 938 |
+
.catch(error => {
|
| 939 |
+
console.error('خطأ في عرض خريطة الشبكة في AR:', error);
|
| 940 |
+
});
|
| 941 |
+
}
|
| 942 |
+
|
| 943 |
+
/**
|
| 944 |
+
* نظام الأحداث
|
| 945 |
+
*/
|
| 946 |
+
emit(eventName, data) {
|
| 947 |
+
if (this.eventListeners[eventName]) {
|
| 948 |
+
this.eventListeners[eventName].forEach(callback => {
|
| 949 |
+
try {
|
| 950 |
+
callback(data);
|
| 951 |
+
} catch (error) {
|
| 952 |
+
console.error('خطأ في مستمع الحدث:', error);
|
| 953 |
+
}
|
| 954 |
+
});
|
| 955 |
+
}
|
| 956 |
+
}
|
| 957 |
+
|
| 958 |
+
on(eventName, callback) {
|
| 959 |
+
if (!this.eventListeners[eventName]) {
|
| 960 |
+
this.eventListeners[eventName] = [];
|
| 961 |
+
}
|
| 962 |
+
this.eventListeners[eventName].push(callback);
|
| 963 |
+
}
|
| 964 |
+
|
| 965 |
+
off(eventName, callback) {
|
| 966 |
+
if (this.eventListeners[eventName]) {
|
| 967 |
+
this.eventListeners[eventName] = this.eventListeners[eventName].filter(cb => cb !== callback);
|
| 968 |
+
}
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
/**
|
| 972 |
+
* تدمير النظام
|
| 973 |
+
*/
|
| 974 |
+
destroy() {
|
| 975 |
+
console.log('🗑️ تدمير AR Controller...');
|
| 976 |
+
|
| 977 |
+
// إنهاء الجلسة النشطة
|
| 978 |
+
if (this.isSessionActive) {
|
| 979 |
+
this.endSession();
|
| 980 |
+
}
|
| 981 |
+
|
| 982 |
+
// تنظيف الموارد
|
| 983 |
+
this.cleanupAnchors();
|
| 984 |
+
this.cleanupPlanes();
|
| 985 |
+
|
| 986 |
+
this.trackedImages.clear();
|
| 987 |
+
this.planes.clear();
|
| 988 |
+
|
| 989 |
+
console.log('✅ تم تدمير AR Controller');
|
| 990 |
+
}
|
| 991 |
+
}
|
| 992 |
+
|
| 993 |
+
// تصدير للاستخدام في الوحدات الأخرى
|
| 994 |
+
if (typeof module !== 'undefined' && module.exports) {
|
| 995 |
+
module.exports = ARController;
|
| 996 |
+
}
|
gesture-controller.js
ADDED
|
@@ -0,0 +1,1002 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* 👋 Gesture Controller - تحكم بالإيماءات
|
| 3 |
+
* نظام متقدم للتعرف على حركات اليد والإيماءات للتحكم في واجهة غامرة
|
| 4 |
+
*
|
| 5 |
+
* المميزات:
|
| 6 |
+
* - التعرف على 20+ إيماءة
|
| 7 |
+
* - تتبع حركة اليدين
|
| 8 |
+
* - تحكم باللمس الافتراضي
|
| 9 |
+
* - إيماءات مخصصة للعربية
|
| 10 |
+
* - دعم متعدد المستخدمين
|
| 11 |
+
*
|
| 12 |
+
* @author MiniMax Agent
|
| 13 |
+
* @version 2025.12.10
|
| 14 |
+
*/
|
| 15 |
+
|
| 16 |
+
class GestureController {
|
| 17 |
+
constructor(videoElement) {
|
| 18 |
+
this.videoElement = videoElement;
|
| 19 |
+
this.canvas = document.createElement('canvas');
|
| 20 |
+
this.ctx = this.canvas.getContext('2d');
|
| 21 |
+
this.isInitialized = false;
|
| 22 |
+
this.isActive = false;
|
| 23 |
+
this.hands = new Map();
|
| 24 |
+
this.gestures = new Map();
|
| 25 |
+
this.gestureHistory = [];
|
| 26 |
+
|
| 27 |
+
// إعدادات التحكم
|
| 28 |
+
this.config = {
|
| 29 |
+
maxHands: 2,
|
| 30 |
+
confidenceThreshold: 0.7,
|
| 31 |
+
enable3DTracking: true,
|
| 32 |
+
gestureSmoothing: 0.3,
|
| 33 |
+
enableCustomGestures: true,
|
| 34 |
+
sensitivity: 1.0,
|
| 35 |
+
enableMultiUser: false
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
// تعريف الإيماءات
|
| 39 |
+
this.defineGestures();
|
| 40 |
+
|
| 41 |
+
// بيانات التتبع
|
| 42 |
+
this.trackingData = {
|
| 43 |
+
lastHandPositions: new Map(),
|
| 44 |
+
gestureStartTime: null,
|
| 45 |
+
currentGesture: null,
|
| 46 |
+
gestureConfidence: 0
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
// محاكاة MediaPipe أو نظام مشابه
|
| 50 |
+
this.mockHandTracking = this.createMockHandTracking();
|
| 51 |
+
|
| 52 |
+
console.log('👋 تم تهيئة Gesture Controller');
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
/**
|
| 56 |
+
* تهيئة النظام
|
| 57 |
+
*/
|
| 58 |
+
async initialize() {
|
| 59 |
+
try {
|
| 60 |
+
console.log('🔧 بدء تهيئة التحكم بالإيماءات...');
|
| 61 |
+
|
| 62 |
+
// إعداد Canvas للمعالجة
|
| 63 |
+
this.canvas.width = this.videoElement.videoWidth || 640;
|
| 64 |
+
this.canvas.height = this.videoElement.videoHeight || 480;
|
| 65 |
+
|
| 66 |
+
// فحص دعم الكاميرا
|
| 67 |
+
if (!this.videoElement.srcObject) {
|
| 68 |
+
throw new Error('لا يوجد مصدر فيديو للكاميرا');
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
// بدء التتبع
|
| 72 |
+
this.startTracking();
|
| 73 |
+
|
| 74 |
+
this.isInitialized = true;
|
| 75 |
+
this.isActive = true;
|
| 76 |
+
|
| 77 |
+
console.log('✅ تم تهيئة التحكم بالإيماءات');
|
| 78 |
+
|
| 79 |
+
return true;
|
| 80 |
+
|
| 81 |
+
} catch (error) {
|
| 82 |
+
console.error('❌ خطأ في تهيئة التحكم بالإيماءات:', error);
|
| 83 |
+
throw error;
|
| 84 |
+
}
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
/**
|
| 88 |
+
* تعريف الإيماءات المدعومة
|
| 89 |
+
*/
|
| 90 |
+
defineGestures() {
|
| 91 |
+
// إيماءات أساسية
|
| 92 |
+
this.gestures.set('hand_open', {
|
| 93 |
+
name: 'اليد مفتوحة',
|
| 94 |
+
description: 'افتح يدك للتحديد',
|
| 95 |
+
confidence: 0.8,
|
| 96 |
+
triggers: ['select', 'confirm']
|
| 97 |
+
});
|
| 98 |
+
|
| 99 |
+
this.gestures.set('hand_closed', {
|
| 100 |
+
name: 'اليد مغلقة',
|
| 101 |
+
description: 'أغلق يدك للإلغاء',
|
| 102 |
+
confidence: 0.8,
|
| 103 |
+
triggers: ['cancel', 'back']
|
| 104 |
+
});
|
| 105 |
+
|
| 106 |
+
this.gestures.set('pointing', {
|
| 107 |
+
name: 'الإشارة',
|
| 108 |
+
description: 'أشر للإشارة إلى عنصر',
|
| 109 |
+
confidence: 0.9,
|
| 110 |
+
triggers: ['select', 'point']
|
| 111 |
+
});
|
| 112 |
+
|
| 113 |
+
this.gestures.set('thumbs_up', {
|
| 114 |
+
name: 'إبهام للأعلى',
|
| 115 |
+
description: 'ارفع إبهامك للموافقة',
|
| 116 |
+
confidence: 0.85,
|
| 117 |
+
triggers: ['confirm', 'approve']
|
| 118 |
+
});
|
| 119 |
+
|
| 120 |
+
this.gestures.set('thumbs_down', {
|
| 121 |
+
name: 'إبهام للأسفل',
|
| 122 |
+
description: 'أشر بإبهامك للأسفل للرفض',
|
| 123 |
+
confidence: 0.85,
|
| 124 |
+
triggers: ['reject', 'deny']
|
| 125 |
+
});
|
| 126 |
+
|
| 127 |
+
// إيماءات متقدمة
|
| 128 |
+
this.gestures.set('swipe_left', {
|
| 129 |
+
name: 'السحب لليسار',
|
| 130 |
+
description: 'حرك يدك من اليمين إلى اليسار',
|
| 131 |
+
confidence: 0.75,
|
| 132 |
+
triggers: ['navigate', 'previous']
|
| 133 |
+
});
|
| 134 |
+
|
| 135 |
+
this.gestures.set('swipe_right', {
|
| 136 |
+
name: 'السحب لليمين',
|
| 137 |
+
description: 'حرك يدك من اليسار إلى اليمين',
|
| 138 |
+
confidence: 0.75,
|
| 139 |
+
triggers: ['navigate', 'next']
|
| 140 |
+
});
|
| 141 |
+
|
| 142 |
+
this.gestures.set('swipe_up', {
|
| 143 |
+
name: 'السحب للأعلى',
|
| 144 |
+
description: 'حرك يدك من أسفل إلى أعلى',
|
| 145 |
+
confidence: 0.75,
|
| 146 |
+
triggers: ['scroll_up', 'zoom_in']
|
| 147 |
+
});
|
| 148 |
+
|
| 149 |
+
this.gestures.set('swipe_down', {
|
| 150 |
+
name: 'السحب للأسفل',
|
| 151 |
+
description: 'حرك يدك من أعلى إلى أسفل',
|
| 152 |
+
confidence: 0.75,
|
| 153 |
+
triggers: ['scroll_down', 'zoom_out']
|
| 154 |
+
});
|
| 155 |
+
|
| 156 |
+
this.gestures.set('pinch', {
|
| 157 |
+
name: 'الإمساك',
|
| 158 |
+
description: 'قرّب إصبعين لبعض للإمساك',
|
| 159 |
+
confidence: 0.8,
|
| 160 |
+
triggers: ['grab', 'hold']
|
| 161 |
+
});
|
| 162 |
+
|
| 163 |
+
this.gestures.set('pinch_out', {
|
| 164 |
+
name: 'فتح الإمساك',
|
| 165 |
+
description: 'افتح إصبعيك للإفلات',
|
| 166 |
+
confidence: 0.8,
|
| 167 |
+
triggers: ['release', 'drop']
|
| 168 |
+
});
|
| 169 |
+
|
| 170 |
+
this.gestures.set('rotate_clockwise', {
|
| 171 |
+
name: 'الدوران عقارب الساعة',
|
| 172 |
+
description: 'حرك يدك في اتجاه عقارب الساعة',
|
| 173 |
+
confidence: 0.7,
|
| 174 |
+
triggers: ['rotate', 'clockwise']
|
| 175 |
+
});
|
| 176 |
+
|
| 177 |
+
this.gestures.set('rotate_counter_clockwise', {
|
| 178 |
+
name: 'الدوران عكس عقارب الساعة',
|
| 179 |
+
description: 'حرك يدك عكس اتجاه عقارب الساعة',
|
| 180 |
+
confidence: 0.7,
|
| 181 |
+
triggers: ['rotate', 'counter_clockwise']
|
| 182 |
+
});
|
| 183 |
+
|
| 184 |
+
// إيماءات صوتية باللغة العربية
|
| 185 |
+
this.gestures.set('call_me', {
|
| 186 |
+
name: 'إشارة النداء',
|
| 187 |
+
description: 'حرك إصبعك نحوك لنداء النظام',
|
| 188 |
+
confidence: 0.75,
|
| 189 |
+
triggers: ['voice_command', 'call']
|
| 190 |
+
});
|
| 191 |
+
|
| 192 |
+
this.gestures.set('stop', {
|
| 193 |
+
name: 'إشارة التوقف',
|
| 194 |
+
description: 'ارفع راحة يدك للتوقف',
|
| 195 |
+
confidence: 0.9,
|
| 196 |
+
triggers: ['stop', 'pause']
|
| 197 |
+
});
|
| 198 |
+
|
| 199 |
+
this.gestures.set('victory', {
|
| 200 |
+
name: 'إشارة النصر',
|
| 201 |
+
description: 'اعرض إصبعين للأعلى للإيجاب',
|
| 202 |
+
confidence: 0.8,
|
| 203 |
+
triggers: ['positive', 'success']
|
| 204 |
+
});
|
| 205 |
+
|
| 206 |
+
this.gestures.set('number_one', {
|
| 207 |
+
name: 'الرقم واحد',
|
| 208 |
+
description: 'ارفع إصبع واحد للتركيز',
|
| 209 |
+
confidence: 0.8,
|
| 210 |
+
triggers: ['focus', 'primary']
|
| 211 |
+
});
|
| 212 |
+
|
| 213 |
+
this.gestures.set('number_two', {
|
| 214 |
+
name: 'الرقم اثنان',
|
| 215 |
+
description: 'ارفع إصبعين للتحديد المتعدد',
|
| 216 |
+
confidence: 0.8,
|
| 217 |
+
triggers: ['multi_select', 'secondary']
|
| 218 |
+
});
|
| 219 |
+
|
| 220 |
+
this.gestures.set('number_three', {
|
| 221 |
+
name: 'الرقم ثلاثة',
|
| 222 |
+
description: 'ارفع ثلاثة أصابع للإعدادات',
|
| 223 |
+
confidence: 0.8,
|
| 224 |
+
triggers: ['settings', 'options']
|
| 225 |
+
});
|
| 226 |
+
|
| 227 |
+
// إيماءات تقنية للأمان السيبراني
|
| 228 |
+
this.gestures.set('shield', {
|
| 229 |
+
name: 'درع الحماية',
|
| 230 |
+
description: 'ارفع يديك كدرع للحماية',
|
| 231 |
+
confidence: 0.7,
|
| 232 |
+
triggers: ['protect', 'defense']
|
| 233 |
+
});
|
| 234 |
+
|
| 235 |
+
this.gestures.set('warning', {
|
| 236 |
+
name: 'تحذير',
|
| 237 |
+
description: 'حرك يدك بتحذير للخطر',
|
| 238 |
+
confidence: 0.75,
|
| 239 |
+
triggers: ['warning', 'alert']
|
| 240 |
+
});
|
| 241 |
+
|
| 242 |
+
this.gestures.set('scan', {
|
| 243 |
+
name: 'فحص',
|
| 244 |
+
description: 'حرك يدك في حركة فحص',
|
| 245 |
+
confidence: 0.7,
|
| 246 |
+
triggers: ['scan', 'analyze']
|
| 247 |
+
});
|
| 248 |
+
|
| 249 |
+
console.log('📝 تم تعريف', this.gestures.size, 'إيماءة');
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
/**
|
| 253 |
+
* إنشاء نظام تتبع وهمية
|
| 254 |
+
*/
|
| 255 |
+
createMockHandTracking() {
|
| 256 |
+
return {
|
| 257 |
+
isTracking: false,
|
| 258 |
+
hands: [],
|
| 259 |
+
|
| 260 |
+
start: () => {
|
| 261 |
+
this.isTracking = true;
|
| 262 |
+
console.log('🎥 بدء تتبع اليدين الوهمي');
|
| 263 |
+
},
|
| 264 |
+
|
| 265 |
+
stop: () => {
|
| 266 |
+
this.isTracking = false;
|
| 267 |
+
this.hands.clear();
|
| 268 |
+
console.log('🛑 توقف تتبع اليدين الوهمي');
|
| 269 |
+
},
|
| 270 |
+
|
| 271 |
+
update: () => {
|
| 272 |
+
if (!this.isTracking) return;
|
| 273 |
+
|
| 274 |
+
// محاكاة كشف اليدين
|
| 275 |
+
this.simulateHandDetection();
|
| 276 |
+
}
|
| 277 |
+
};
|
| 278 |
+
}
|
| 279 |
+
|
| 280 |
+
/**
|
| 281 |
+
* محاكاة كشف اليدين
|
| 282 |
+
*/
|
| 283 |
+
simulateHandDetection() {
|
| 284 |
+
const time = Date.now() * 0.001;
|
| 285 |
+
|
| 286 |
+
// محاكاة يد واحدة أو اثنتين
|
| 287 |
+
const handCount = Math.random() > 0.3 ? 1 : 0;
|
| 288 |
+
this.hands.clear();
|
| 289 |
+
|
| 290 |
+
for (let i = 0; i < handCount; i++) {
|
| 291 |
+
const hand = {
|
| 292 |
+
id: `hand_${i}`,
|
| 293 |
+
handedness: i === 0 ? 'right' : 'left',
|
| 294 |
+
landmarks: this.generateHandLandmarks(time, i),
|
| 295 |
+
confidence: 0.8 + Math.random() * 0.2,
|
| 296 |
+
timestamp: Date.now()
|
| 297 |
+
};
|
| 298 |
+
|
| 299 |
+
this.hands.set(hand.id, hand);
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
// معالجة الإيماءات إذا تم اكتشاف يد
|
| 303 |
+
if (this.hands.size > 0) {
|
| 304 |
+
this.processGestures();
|
| 305 |
+
}
|
| 306 |
+
}
|
| 307 |
+
|
| 308 |
+
/**
|
| 309 |
+
* توليد معالم اليد الوهمية
|
| 310 |
+
*/
|
| 311 |
+
generateHandLandmarks(time, handIndex) {
|
| 312 |
+
const landmarks = [];
|
| 313 |
+
|
| 314 |
+
// 21 نقطة معلم لليد (MediaPipe Hands format)
|
| 315 |
+
for (let i = 0; i < 21; i++) {
|
| 316 |
+
// محاكاة حركة طبيعية لليد
|
| 317 |
+
const baseX = 0.3 + handIndex * 0.4;
|
| 318 |
+
const baseY = 0.5;
|
| 319 |
+
const baseZ = 0;
|
| 320 |
+
|
| 321 |
+
let x, y, z;
|
| 322 |
+
|
| 323 |
+
if (i < 5) {
|
| 324 |
+
// الإبهام
|
| 325 |
+
x = baseX + Math.sin(time * 0.5 + i * 0.3) * 0.1;
|
| 326 |
+
y = baseY + Math.cos(time * 0.7 + i * 0.2) * 0.05;
|
| 327 |
+
} else if (i < 9) {
|
| 328 |
+
// السبابة
|
| 329 |
+
x = baseX + Math.sin(time * 0.6 + (i-5) * 0.2) * 0.08;
|
| 330 |
+
y = baseY - 0.1 - (i-5) * 0.03 + Math.sin(time * 0.8) * 0.02;
|
| 331 |
+
} else if (i < 13) {
|
| 332 |
+
// الأوسط
|
| 333 |
+
x = baseX + Math.sin(time * 0.4 + (i-9) * 0.25) * 0.08;
|
| 334 |
+
y = baseY - 0.12 - (i-9) * 0.03 + Math.cos(time * 0.9) * 0.02;
|
| 335 |
+
} else if (i < 17) {
|
| 336 |
+
// البنصر
|
| 337 |
+
x = baseX + Math.sin(time * 0.5 + (i-13) * 0.2) * 0.07;
|
| 338 |
+
y = baseY - 0.11 - (i-13) * 0.03 + Math.sin(time * 1.0) * 0.02;
|
| 339 |
+
} else {
|
| 340 |
+
// الخنصر
|
| 341 |
+
x = baseX + Math.sin(time * 0.7 + (i-17) * 0.15) * 0.06;
|
| 342 |
+
y = baseY - 0.1 - (i-17) * 0.03 + Math.cos(time * 1.2) * 0.02;
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
z = baseZ + Math.sin(time * 0.3 + i * 0.1) * 0.02;
|
| 346 |
+
|
| 347 |
+
landmarks.push({ x, y, z });
|
| 348 |
+
}
|
| 349 |
+
|
| 350 |
+
return landmarks;
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
/**
|
| 354 |
+
* بدء التتبع
|
| 355 |
+
*/
|
| 356 |
+
startTracking() {
|
| 357 |
+
if (!this.isInitialized) {
|
| 358 |
+
throw new Error('Gesture Controller غير مهيأ');
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
this.isActive = true;
|
| 362 |
+
this.mockHandTracking.start();
|
| 363 |
+
this.startTrackingLoop();
|
| 364 |
+
|
| 365 |
+
console.log('🎯 بدء تتبع الإيماءات');
|
| 366 |
+
this.emit('tracking_started');
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
/**
|
| 370 |
+
* إيقاف التتبع
|
| 371 |
+
*/
|
| 372 |
+
stopTracking() {
|
| 373 |
+
this.isActive = false;
|
| 374 |
+
this.mockHandTracking.stop();
|
| 375 |
+
|
| 376 |
+
console.log('🛑 توقف تتبع الإيماءات');
|
| 377 |
+
this.emit('tracking_stopped');
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
/**
|
| 381 |
+
* بدء حلقة التتبع
|
| 382 |
+
*/
|
| 383 |
+
startTrackingLoop() {
|
| 384 |
+
const track = () => {
|
| 385 |
+
if (!this.isActive) return;
|
| 386 |
+
|
| 387 |
+
try {
|
| 388 |
+
// تحديث التتبع
|
| 389 |
+
this.mockHandTracking.update();
|
| 390 |
+
|
| 391 |
+
// تحديث المعالم
|
| 392 |
+
this.updateHandLandmarks();
|
| 393 |
+
|
| 394 |
+
// طلب الإطار التالي
|
| 395 |
+
requestAnimationFrame(track);
|
| 396 |
+
|
| 397 |
+
} catch (error) {
|
| 398 |
+
console.error('خطأ في حلقة التتبع:', error);
|
| 399 |
+
setTimeout(track, 100); // محاولة إعادة التتبع
|
| 400 |
+
}
|
| 401 |
+
};
|
| 402 |
+
|
| 403 |
+
track();
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
/**
|
| 407 |
+
* تحديث معالم اليد
|
| 408 |
+
*/
|
| 409 |
+
updateHandLandmarks() {
|
| 410 |
+
this.hands.forEach((hand, handId) => {
|
| 411 |
+
// تطبيق التنعيم على المعالم
|
| 412 |
+
hand.landmarks = this.smoothLandmarks(hand.landmarks, handId);
|
| 413 |
+
|
| 414 |
+
// تحديد موقع اليد في الشاشة
|
| 415 |
+
hand.screenPosition = this.calculateScreenPosition(hand.landmarks);
|
| 416 |
+
});
|
| 417 |
+
}
|
| 418 |
+
|
| 419 |
+
/**
|
| 420 |
+
* تنعيم المعالم
|
| 421 |
+
*/
|
| 422 |
+
smoothLandmarks(landmarks, handId) {
|
| 423 |
+
const lastPositions = this.trackingData.lastHandPositions.get(handId) || [];
|
| 424 |
+
const smoothed = [];
|
| 425 |
+
|
| 426 |
+
for (let i = 0; i < landmarks.length; i++) {
|
| 427 |
+
const current = landmarks[i];
|
| 428 |
+
const last = lastPositions[i] || current;
|
| 429 |
+
|
| 430 |
+
// تطبيق التنعيم
|
| 431 |
+
const alpha = this.config.gestureSmoothing;
|
| 432 |
+
const smoothedPoint = {
|
| 433 |
+
x: last.x * (1 - alpha) + current.x * alpha,
|
| 434 |
+
y: last.y * (1 - alpha) + current.y * alpha,
|
| 435 |
+
z: last.z * (1 - alpha) + current.z * alpha
|
| 436 |
+
};
|
| 437 |
+
|
| 438 |
+
smoothed.push(smoothedPoint);
|
| 439 |
+
}
|
| 440 |
+
|
| 441 |
+
// حفظ المواقع المحدثة
|
| 442 |
+
this.trackingData.lastHandPositions.set(handId, smoothed);
|
| 443 |
+
|
| 444 |
+
return smoothed;
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
/**
|
| 448 |
+
* حساب موقع الشاشة
|
| 449 |
+
*/
|
| 450 |
+
calculateScreenPosition(landmarks) {
|
| 451 |
+
if (landmarks.length === 0) return null;
|
| 452 |
+
|
| 453 |
+
// استخدام نقطة منتصف راحة اليد (النقطة 9)
|
| 454 |
+
const palm = landmarks[9];
|
| 455 |
+
|
| 456 |
+
// تحويل من إحداثيات معيارية إلى إحداثيات شاشة
|
| 457 |
+
const x = palm.x * this.canvas.width;
|
| 458 |
+
const y = palm.y * this.canvas.height;
|
| 459 |
+
|
| 460 |
+
return { x, y };
|
| 461 |
+
}
|
| 462 |
+
|
| 463 |
+
/**
|
| 464 |
+
* معالجة الإيماءات
|
| 465 |
+
*/
|
| 466 |
+
processGestures() {
|
| 467 |
+
this.hands.forEach(hand => {
|
| 468 |
+
const gesture = this.recognizeGesture(hand);
|
| 469 |
+
|
| 470 |
+
if (gesture) {
|
| 471 |
+
this.handleRecognizedGesture(hand, gesture);
|
| 472 |
+
}
|
| 473 |
+
});
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
/**
|
| 477 |
+
* التعرف على الإيماءة
|
| 478 |
+
*/
|
| 479 |
+
recognizeGesture(hand) {
|
| 480 |
+
const landmarks = hand.landmarks;
|
| 481 |
+
|
| 482 |
+
if (landmarks.length < 21) return null;
|
| 483 |
+
|
| 484 |
+
// فحص الإيماءات المختلفة
|
| 485 |
+
for (const [gestureId, gestureData] of this.gestures) {
|
| 486 |
+
const confidence = this.calculateGestureConfidence(gestureId, landmarks);
|
| 487 |
+
|
| 488 |
+
if (confidence >= gestureData.confidence * this.config.sensitivity) {
|
| 489 |
+
return {
|
| 490 |
+
id: gestureId,
|
| 491 |
+
data: gestureData,
|
| 492 |
+
confidence: confidence,
|
| 493 |
+
hand: hand
|
| 494 |
+
};
|
| 495 |
+
}
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
return null;
|
| 499 |
+
}
|
| 500 |
+
|
| 501 |
+
/**
|
| 502 |
+
* حساب الثقة في الإيماءة
|
| 503 |
+
*/
|
| 504 |
+
calculateGestureConfidence(gestureId, landmarks) {
|
| 505 |
+
switch (gestureId) {
|
| 506 |
+
case 'hand_open':
|
| 507 |
+
return this.checkHandOpen(landmarks);
|
| 508 |
+
|
| 509 |
+
case 'hand_closed':
|
| 510 |
+
return this.checkHandClosed(landmarks);
|
| 511 |
+
|
| 512 |
+
case 'pointing':
|
| 513 |
+
return this.checkPointing(landmarks);
|
| 514 |
+
|
| 515 |
+
case 'swipe_left':
|
| 516 |
+
return this.checkSwipeGesture(landmarks, 'left');
|
| 517 |
+
|
| 518 |
+
case 'swipe_right':
|
| 519 |
+
return this.checkSwipeGesture(landmarks, 'right');
|
| 520 |
+
|
| 521 |
+
case 'swipe_up':
|
| 522 |
+
return this.checkSwipeGesture(landmarks, 'up');
|
| 523 |
+
|
| 524 |
+
case 'swipe_down':
|
| 525 |
+
return this.checkSwipeGesture(landmarks, 'down');
|
| 526 |
+
|
| 527 |
+
case 'pinch':
|
| 528 |
+
return this.checkPinch(landmarks);
|
| 529 |
+
|
| 530 |
+
case 'pinch_out':
|
| 531 |
+
return this.checkPinchOut(landmarks);
|
| 532 |
+
|
| 533 |
+
case 'thumbs_up':
|
| 534 |
+
return this.checkThumbsUp(landmarks);
|
| 535 |
+
|
| 536 |
+
case 'thumbs_down':
|
| 537 |
+
return this.checkThumbsDown(landmarks);
|
| 538 |
+
|
| 539 |
+
case 'victory':
|
| 540 |
+
return this.checkVictory(landmarks);
|
| 541 |
+
|
| 542 |
+
case 'number_one':
|
| 543 |
+
return this.checkNumberOne(landmarks);
|
| 544 |
+
|
| 545 |
+
case 'number_two':
|
| 546 |
+
return this.checkNumberTwo(landmarks);
|
| 547 |
+
|
| 548 |
+
case 'number_three':
|
| 549 |
+
return this.checkNumberThree(landmarks);
|
| 550 |
+
|
| 551 |
+
default:
|
| 552 |
+
return 0;
|
| 553 |
+
}
|
| 554 |
+
}
|
| 555 |
+
|
| 556 |
+
/**
|
| 557 |
+
* فحص اليد المفتوحة
|
| 558 |
+
*/
|
| 559 |
+
checkHandOpen(landmarks) {
|
| 560 |
+
// فحص المسافة بين أطراف الأصابع والرسغ
|
| 561 |
+
const wrist = landmarks[0];
|
| 562 |
+
let fingerCount = 0;
|
| 563 |
+
|
| 564 |
+
const fingerTips = [4, 8, 12, 16, 20]; // أطراف الأصابع
|
| 565 |
+
|
| 566 |
+
for (const tip of fingerTips) {
|
| 567 |
+
const distance = this.calculateDistance(landmarks[tip], wrist);
|
| 568 |
+
if (distance > 0.1) fingerCount++;
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
return fingerCount >= 4 ? 0.9 : 0.3;
|
| 572 |
+
}
|
| 573 |
+
|
| 574 |
+
/**
|
| 575 |
+
* فحص اليد المغلقة
|
| 576 |
+
*/
|
| 577 |
+
checkHandClosed(landmarks) {
|
| 578 |
+
// فحص اقتراب أطراف الأصابع من راحة اليد
|
| 579 |
+
const palm = landmarks[9];
|
| 580 |
+
let closeCount = 0;
|
| 581 |
+
|
| 582 |
+
const fingerTips = [4, 8, 12, 16, 20];
|
| 583 |
+
|
| 584 |
+
for (const tip of fingerTips) {
|
| 585 |
+
const distance = this.calculateDistance(landmarks[tip], palm);
|
| 586 |
+
if (distance < 0.05) closeCount++;
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
return closeCount >= 4 ? 0.9 : 0.2;
|
| 590 |
+
}
|
| 591 |
+
|
| 592 |
+
/**
|
| 593 |
+
* فحص الإشارة
|
| 594 |
+
*/
|
| 595 |
+
checkPointing(landmarks) {
|
| 596 |
+
// فحص امتداد السبابة مع بقية الأصابع مطوية
|
| 597 |
+
const indexTip = landmarks[8];
|
| 598 |
+
const indexPip = landmarks[6];
|
| 599 |
+
const middleTip = landmarks[12];
|
| 600 |
+
const ringTip = landmarks[16];
|
| 601 |
+
const pinkyTip = landmarks[20];
|
| 602 |
+
|
| 603 |
+
const indexExtended = this.calculateDistance(indexTip, indexPip) > 0.08;
|
| 604 |
+
const othersClosed = this.calculateDistance(middleTip, landmarks[9]) < 0.06 &&
|
| 605 |
+
this.calculateDistance(ringTip, landmarks[9]) < 0.06 &&
|
| 606 |
+
this.calculateDistance(pinkyTip, landmarks[9]) < 0.06;
|
| 607 |
+
|
| 608 |
+
return (indexExtended && othersClosed) ? 0.85 : 0.2;
|
| 609 |
+
}
|
| 610 |
+
|
| 611 |
+
/**
|
| 612 |
+
* فحص إيماءة السحب
|
| 613 |
+
*/
|
| 614 |
+
checkSwipeGesture(landmarks, direction) {
|
| 615 |
+
const time = Date.now() * 0.001;
|
| 616 |
+
const currentPos = landmarks[9]; // راحة اليد
|
| 617 |
+
|
| 618 |
+
// مقارنة مع الموقع السابق
|
| 619 |
+
const lastPos = this.trackingData.lastHandPositions.get('swipe_history') || [];
|
| 620 |
+
if (lastPos.length < 2) return 0;
|
| 621 |
+
|
| 622 |
+
const deltaX = currentPos.x - lastPos[lastPos.length - 2].x;
|
| 623 |
+
const deltaY = currentPos.y - lastPos[lastPos.length - 2].y;
|
| 624 |
+
|
| 625 |
+
// حفظ الموقع الحالي
|
| 626 |
+
lastPos.push(currentPos);
|
| 627 |
+
if (lastPos.length > 10) lastPos.shift();
|
| 628 |
+
this.trackingData.lastHandPositions.set('swipe_history', lastPos);
|
| 629 |
+
|
| 630 |
+
const threshold = 0.05;
|
| 631 |
+
|
| 632 |
+
switch (direction) {
|
| 633 |
+
case 'left':
|
| 634 |
+
return deltaX < -threshold ? 0.8 : 0.1;
|
| 635 |
+
case 'right':
|
| 636 |
+
return deltaX > threshold ? 0.8 : 0.1;
|
| 637 |
+
case 'up':
|
| 638 |
+
return deltaY < -threshold ? 0.8 : 0.1;
|
| 639 |
+
case 'down':
|
| 640 |
+
return deltaY > threshold ? 0.8 : 0.1;
|
| 641 |
+
default:
|
| 642 |
+
return 0;
|
| 643 |
+
}
|
| 644 |
+
}
|
| 645 |
+
|
| 646 |
+
/**
|
| 647 |
+
* فحص الإمساك
|
| 648 |
+
*/
|
| 649 |
+
checkPinch(landmarks) {
|
| 650 |
+
const thumbTip = landmarks[4];
|
| 651 |
+
const indexTip = landmarks[8];
|
| 652 |
+
const distance = this.calculateDistance(thumbTip, indexTip);
|
| 653 |
+
|
| 654 |
+
return distance < 0.03 ? 0.9 : 0.2;
|
| 655 |
+
}
|
| 656 |
+
|
| 657 |
+
/**
|
| 658 |
+
* فحص فتح الإمساك
|
| 659 |
+
*/
|
| 660 |
+
checkPinchOut(landmarks) {
|
| 661 |
+
const thumbTip = landmarks[4];
|
| 662 |
+
const indexTip = landmarks[8];
|
| 663 |
+
const distance = this.calculateDistance(thumbTip, indexTip);
|
| 664 |
+
|
| 665 |
+
return distance > 0.08 ? 0.9 : 0.2;
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
/**
|
| 669 |
+
* فحص الإبهام للأعلى
|
| 670 |
+
*/
|
| 671 |
+
checkThumbsUp(landmarks) {
|
| 672 |
+
const thumbTip = landmarks[4];
|
| 673 |
+
const thumbIp = landmarks[3];
|
| 674 |
+
const indexTip = landmarks[8];
|
| 675 |
+
const middleTip = landmarks[12];
|
| 676 |
+
|
| 677 |
+
const thumbUp = thumbTip.y < thumbIp.y - 0.02;
|
| 678 |
+
const othersDown = this.calculateDistance(indexTip, landmarks[9]) < 0.06 &&
|
| 679 |
+
this.calculateDistance(middleTip, landmarks[9]) < 0.06;
|
| 680 |
+
|
| 681 |
+
return (thumbUp && othersDown) ? 0.85 : 0.2;
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
/**
|
| 685 |
+
* فحص الإبهام للأسفل
|
| 686 |
+
*/
|
| 687 |
+
checkThumbsDown(landmarks) {
|
| 688 |
+
const thumbTip = landmarks[4];
|
| 689 |
+
const thumbIp = landmarks[3];
|
| 690 |
+
const indexTip = landmarks[8];
|
| 691 |
+
const middleTip = landmarks[12];
|
| 692 |
+
|
| 693 |
+
const thumbDown = thumbTip.y > thumbIp.y + 0.02;
|
| 694 |
+
const othersDown = this.calculateDistance(indexTip, landmarks[9]) < 0.06 &&
|
| 695 |
+
this.calculateDistance(middleTip, landmarks[9]) < 0.06;
|
| 696 |
+
|
| 697 |
+
return (thumbDown && othersDown) ? 0.85 : 0.2;
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
/**
|
| 701 |
+
* فحص إشارة النصر
|
| 702 |
+
*/
|
| 703 |
+
checkVictory(landmarks) {
|
| 704 |
+
const indexTip = landmarks[8];
|
| 705 |
+
const middleTip = landmarks[12];
|
| 706 |
+
const indexPip = landmarks[6];
|
| 707 |
+
const middlePip = landmarks[10];
|
| 708 |
+
|
| 709 |
+
const bothUp = indexTip.y < indexPip.y && middleTip.y < middlePip.y;
|
| 710 |
+
const distance = this.calculateDistance(indexTip, middleTip);
|
| 711 |
+
const closeTogether = distance < 0.04;
|
| 712 |
+
|
| 713 |
+
return (bothUp && closeTogether) ? 0.8 : 0.2;
|
| 714 |
+
}
|
| 715 |
+
|
| 716 |
+
/**
|
| 717 |
+
* فحص الرقم واحد
|
| 718 |
+
*/
|
| 719 |
+
checkNumberOne(landmarks) {
|
| 720 |
+
const indexTip = landmarks[8];
|
| 721 |
+
const indexPip = landmarks[6];
|
| 722 |
+
const middleTip = landmarks[12];
|
| 723 |
+
const ringTip = landmarks[16];
|
| 724 |
+
const pinkyTip = landmarks[20];
|
| 725 |
+
|
| 726 |
+
const indexExtended = indexTip.y < indexPip.y - 0.02;
|
| 727 |
+
const othersDown = this.calculateDistance(middleTip, landmarks[9]) < 0.06 &&
|
| 728 |
+
this.calculateDistance(ringTip, landmarks[9]) < 0.06 &&
|
| 729 |
+
this.calculateDistance(pinkyTip, landmarks[9]) < 0.06;
|
| 730 |
+
|
| 731 |
+
return (indexExtended && othersDown) ? 0.8 : 0.2;
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
/**
|
| 735 |
+
* فحص الرقم اثنان
|
| 736 |
+
*/
|
| 737 |
+
checkNumberTwo(landmarks) {
|
| 738 |
+
const indexTip = landmarks[8];
|
| 739 |
+
const middleTip = landmarks[12];
|
| 740 |
+
const indexPip = landmarks[6];
|
| 741 |
+
const middlePip = landmarks[10];
|
| 742 |
+
|
| 743 |
+
const indexUp = indexTip.y < indexPip.y - 0.02;
|
| 744 |
+
const middleUp = middleTip.y < middlePip.y - 0.02;
|
| 745 |
+
const ringDown = this.calculateDistance(landmarks[16], landmarks[9]) < 0.06;
|
| 746 |
+
const pinkyDown = this.calculateDistance(landmarks[20], landmarks[9]) < 0.06;
|
| 747 |
+
|
| 748 |
+
return (indexUp && middleUp && ringDown && pinkyDown) ? 0.8 : 0.2;
|
| 749 |
+
}
|
| 750 |
+
|
| 751 |
+
/**
|
| 752 |
+
* فحص الرقم ثلاثة
|
| 753 |
+
*/
|
| 754 |
+
checkNumberThree(landmarks) {
|
| 755 |
+
const indexTip = landmarks[8];
|
| 756 |
+
const middleTip = landmarks[12];
|
| 757 |
+
const ringTip = landmarks[16];
|
| 758 |
+
const indexPip = landmarks[6];
|
| 759 |
+
const middlePip = landmarks[10];
|
| 760 |
+
const ringPip = landmarks[14];
|
| 761 |
+
|
| 762 |
+
const indexUp = indexTip.y < indexPip.y - 0.02;
|
| 763 |
+
const middleUp = middleTip.y < middlePip.y - 0.02;
|
| 764 |
+
const ringUp = ringTip.y < ringPip.y - 0.02;
|
| 765 |
+
const pinkyDown = this.calculateDistance(landmarks[20], landmarks[9]) < 0.06;
|
| 766 |
+
|
| 767 |
+
return (indexUp && middleUp && ringUp && pinkyDown) ? 0.8 : 0.2;
|
| 768 |
+
}
|
| 769 |
+
|
| 770 |
+
/**
|
| 771 |
+
* حساب المسافة بين نقطتين
|
| 772 |
+
*/
|
| 773 |
+
calculateDistance(point1, point2) {
|
| 774 |
+
const dx = point1.x - point2.x;
|
| 775 |
+
const dy = point1.y - point2.y;
|
| 776 |
+
const dz = point1.z - point2.z;
|
| 777 |
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
| 778 |
+
}
|
| 779 |
+
|
| 780 |
+
/**
|
| 781 |
+
* معالجة الإيماءة المعترف بها
|
| 782 |
+
*/
|
| 783 |
+
handleRecognizedGesture(hand, gesture) {
|
| 784 |
+
const now = Date.now();
|
| 785 |
+
|
| 786 |
+
// فحص التكرار والإيماءة الجديدة
|
| 787 |
+
const lastGesture = this.gestureHistory[this.gestureHistory.length - 1];
|
| 788 |
+
|
| 789 |
+
if (!lastGesture || lastGesture.id !== gesture.id ||
|
| 790 |
+
(now - lastGesture.timestamp) > 1000) { // ثانية واحدة بين الإيماءات
|
| 791 |
+
|
| 792 |
+
console.log('👋 إيماءة معترف بها:', gesture.data.name, `(الثقة: ${Math.round(gesture.confidence * 100)}%)`);
|
| 793 |
+
|
| 794 |
+
// حفظ في التاريخ
|
| 795 |
+
this.gestureHistory.push({
|
| 796 |
+
id: gesture.id,
|
| 797 |
+
data: gesture.data,
|
| 798 |
+
confidence: gesture.confidence,
|
| 799 |
+
hand: hand,
|
| 800 |
+
timestamp: now,
|
| 801 |
+
screenPosition: hand.screenPosition
|
| 802 |
+
});
|
| 803 |
+
|
| 804 |
+
// الاحتفاظ بآخر 50 إيماءة فقط
|
| 805 |
+
if (this.gestureHistory.length > 50) {
|
| 806 |
+
this.gestureHistory.shift();
|
| 807 |
+
}
|
| 808 |
+
|
| 809 |
+
// إرسال الأحداث
|
| 810 |
+
this.emit('gesture_recognized', gesture);
|
| 811 |
+
|
| 812 |
+
// تنفيذ الإجراءات المرتبطة
|
| 813 |
+
this.executeGestureActions(gesture);
|
| 814 |
+
}
|
| 815 |
+
}
|
| 816 |
+
|
| 817 |
+
/**
|
| 818 |
+
* تنفيذ إجراءات الإيماءة
|
| 819 |
+
*/
|
| 820 |
+
executeGestureActions(gesture) {
|
| 821 |
+
const actions = gesture.data.triggers;
|
| 822 |
+
|
| 823 |
+
actions.forEach(action => {
|
| 824 |
+
console.log('⚡ تنفيذ إجراء:', action);
|
| 825 |
+
this.emit(`gesture_${action}`, gesture);
|
| 826 |
+
});
|
| 827 |
+
|
| 828 |
+
// إجراءات خاصة بالإيماءة
|
| 829 |
+
switch (gesture.id) {
|
| 830 |
+
case 'pointing':
|
| 831 |
+
this.emit('hand_detected', {
|
| 832 |
+
position: gesture.hand.screenPosition,
|
| 833 |
+
confidence: gesture.confidence
|
| 834 |
+
});
|
| 835 |
+
break;
|
| 836 |
+
|
| 837 |
+
case 'swipe_left':
|
| 838 |
+
this.emit('swipe_left', gesture);
|
| 839 |
+
break;
|
| 840 |
+
|
| 841 |
+
case 'swipe_right':
|
| 842 |
+
this.emit('swipe_right', gesture);
|
| 843 |
+
break;
|
| 844 |
+
|
| 845 |
+
case 'pinch':
|
| 846 |
+
this.emit('pinch', {
|
| 847 |
+
position: gesture.hand.screenPosition,
|
| 848 |
+
confidence: gesture.confidence
|
| 849 |
+
});
|
| 850 |
+
break;
|
| 851 |
+
|
| 852 |
+
case 'pinch_out':
|
| 853 |
+
this.emit('pinch_out', gesture);
|
| 854 |
+
break;
|
| 855 |
+
|
| 856 |
+
case 'call_me':
|
| 857 |
+
this.emit('voice_command', gesture);
|
| 858 |
+
break;
|
| 859 |
+
|
| 860 |
+
case 'stop':
|
| 861 |
+
this.emit('emergency_stop', gesture);
|
| 862 |
+
break;
|
| 863 |
+
}
|
| 864 |
+
}
|
| 865 |
+
|
| 866 |
+
/**
|
| 867 |
+
* الحصول على قائمة الإيماءات المدعومة
|
| 868 |
+
*/
|
| 869 |
+
getSupportedGestures() {
|
| 870 |
+
const gestures = [];
|
| 871 |
+
this.gestures.forEach((data, id) => {
|
| 872 |
+
gestures.push({
|
| 873 |
+
id: id,
|
| 874 |
+
name: data.name,
|
| 875 |
+
description: data.description,
|
| 876 |
+
triggers: data.triggers
|
| 877 |
+
});
|
| 878 |
+
});
|
| 879 |
+
return gestures;
|
| 880 |
+
}
|
| 881 |
+
|
| 882 |
+
/**
|
| 883 |
+
* الحصول على تاريخ الإيماءات
|
| 884 |
+
*/
|
| 885 |
+
getGestureHistory(limit = 10) {
|
| 886 |
+
return this.gestureHistory.slice(-limit);
|
| 887 |
+
}
|
| 888 |
+
|
| 889 |
+
/**
|
| 890 |
+
* الحصول على حالة التتبع
|
| 891 |
+
*/
|
| 892 |
+
getTrackingState() {
|
| 893 |
+
return {
|
| 894 |
+
isActive: this.isActive,
|
| 895 |
+
isInitialized: this.isInitialized,
|
| 896 |
+
handsDetected: this.hands.size,
|
| 897 |
+
lastGesture: this.gestureHistory[this.gestureHistory.length - 1] || null,
|
| 898 |
+
supportedGestures: this.gestures.size,
|
| 899 |
+
config: this.config
|
| 900 |
+
};
|
| 901 |
+
}
|
| 902 |
+
|
| 903 |
+
/**
|
| 904 |
+
* تحديث إعدادات التحكم
|
| 905 |
+
*/
|
| 906 |
+
updateConfig(newConfig) {
|
| 907 |
+
this.config = { ...this.config, ...newConfig };
|
| 908 |
+
console.log('🔧 تم تحديث إعدادات التحكم بالإيماءات:', this.config);
|
| 909 |
+
}
|
| 910 |
+
|
| 911 |
+
/**
|
| 912 |
+
* إضافة إيماءة مخصصة
|
| 913 |
+
*/
|
| 914 |
+
addCustomGesture(id, name, description, callback) {
|
| 915 |
+
this.gestures.set(id, {
|
| 916 |
+
name: name,
|
| 917 |
+
description: description,
|
| 918 |
+
confidence: 0.7,
|
| 919 |
+
triggers: ['custom'],
|
| 920 |
+
callback: callback
|
| 921 |
+
});
|
| 922 |
+
|
| 923 |
+
console.log('✨ تم إضافة إيماءة مخصصة:', id);
|
| 924 |
+
}
|
| 925 |
+
|
| 926 |
+
/**
|
| 927 |
+
* محاكاة إيماءة للاختبار
|
| 928 |
+
*/
|
| 929 |
+
simulateGesture(gestureId) {
|
| 930 |
+
const gesture = this.gestures.get(gestureId);
|
| 931 |
+
if (!gesture) {
|
| 932 |
+
console.warn('إيماءة غير موجودة:', gestureId);
|
| 933 |
+
return;
|
| 934 |
+
}
|
| 935 |
+
|
| 936 |
+
const mockHand = {
|
| 937 |
+
id: 'mock_hand',
|
| 938 |
+
handedness: 'right',
|
| 939 |
+
landmarks: this.generateHandLandmarks(Date.now() * 0.001, 0),
|
| 940 |
+
confidence: 0.9,
|
| 941 |
+
screenPosition: { x: 320, y: 240 },
|
| 942 |
+
timestamp: Date.now()
|
| 943 |
+
};
|
| 944 |
+
|
| 945 |
+
const recognizedGesture = {
|
| 946 |
+
id: gestureId,
|
| 947 |
+
data: gesture,
|
| 948 |
+
confidence: 0.9,
|
| 949 |
+
hand: mockHand
|
| 950 |
+
};
|
| 951 |
+
|
| 952 |
+
this.handleRecognizedGesture(mockHand, recognizedGesture);
|
| 953 |
+
console.log('🎭 تم محاكاة إيماءة:', gestureId);
|
| 954 |
+
}
|
| 955 |
+
|
| 956 |
+
/**
|
| 957 |
+
* نظام الأحداث
|
| 958 |
+
*/
|
| 959 |
+
emit(eventName, data) {
|
| 960 |
+
if (this.eventListeners[eventName]) {
|
| 961 |
+
this.eventListeners[eventName].forEach(callback => {
|
| 962 |
+
try {
|
| 963 |
+
callback(data);
|
| 964 |
+
} catch (error) {
|
| 965 |
+
console.error('خطأ في مستمع الحدث:', error);
|
| 966 |
+
}
|
| 967 |
+
});
|
| 968 |
+
}
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
on(eventName, callback) {
|
| 972 |
+
if (!this.eventListeners[eventName]) {
|
| 973 |
+
this.eventListeners[eventName] = [];
|
| 974 |
+
}
|
| 975 |
+
this.eventListeners[eventName].push(callback);
|
| 976 |
+
}
|
| 977 |
+
|
| 978 |
+
off(eventName, callback) {
|
| 979 |
+
if (this.eventListeners[eventName]) {
|
| 980 |
+
this.eventListeners[eventName] = this.eventListeners[eventName].filter(cb => cb !== callback);
|
| 981 |
+
}
|
| 982 |
+
}
|
| 983 |
+
|
| 984 |
+
/**
|
| 985 |
+
* تدمير النظام
|
| 986 |
+
*/
|
| 987 |
+
destroy() {
|
| 988 |
+
console.log('🗑️ تدمير Gesture Controller...');
|
| 989 |
+
|
| 990 |
+
this.stopTracking();
|
| 991 |
+
this.hands.clear();
|
| 992 |
+
this.gestureHistory = [];
|
| 993 |
+
this.trackingData.lastHandPositions.clear();
|
| 994 |
+
|
| 995 |
+
console.log('✅ تم تدمير Gesture Controller');
|
| 996 |
+
}
|
| 997 |
+
}
|
| 998 |
+
|
| 999 |
+
// تصدير للاستخدام في الوحدات الأخرى
|
| 1000 |
+
if (typeof module !== 'undefined' && module.exports) {
|
| 1001 |
+
module.exports = GestureController;
|
| 1002 |
+
}
|
holographic-security-center.html
ADDED
|
@@ -0,0 +1,534 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="ar" dir="rtl">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>مركز القيادة السيبراني الغامر - Holographic Security Command Center</title>
|
| 7 |
+
<meta name="description" content="مركز قيادة سيبراني ثوري بتقنيات الواقع الافتراضي والمجسمات ثلاثية الأبعاد">
|
| 8 |
+
<meta name="keywords" content="أمن سيبراني, واقع افتراضي, أمان, تهديدات, مجسمات ثلاثية الأبعاد">
|
| 9 |
+
<meta name="author" content="MiniMax Agent">
|
| 10 |
+
|
| 11 |
+
<!-- Preload critical resources -->
|
| 12 |
+
<link rel="preload" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&display=swap" as="style">
|
| 13 |
+
<link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js" as="script">
|
| 14 |
+
|
| 15 |
+
<!-- Fonts -->
|
| 16 |
+
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
| 17 |
+
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600&display=swap" rel="stylesheet">
|
| 18 |
+
|
| 19 |
+
<!-- Favicon -->
|
| 20 |
+
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><circle cx='50' cy='50' r='40' fill='%2322d3ee'/><circle cx='50' cy='50' r='20' fill='%23000000'/><circle cx='50' cy='50' r='10' fill='%2322d3ee'/></svg>">
|
| 21 |
+
|
| 22 |
+
<!-- PWA Manifest -->
|
| 23 |
+
<link rel="manifest" href="data:application/json,{'name':'مركز القيادة الغامر','short_name':'قيادة غامرة','description':'مركز قيادة سيبراني بتقنيات متقدمة','start_url':'/','display':'fullscreen','theme_color':'%23000000','background_color':'%23000000','orientation':'landscape'}">
|
| 24 |
+
|
| 25 |
+
<!-- Critical CSS -->
|
| 26 |
+
<style>
|
| 27 |
+
/* Critical above-the-fold styles */
|
| 28 |
+
* {
|
| 29 |
+
margin: 0;
|
| 30 |
+
padding: 0;
|
| 31 |
+
box-sizing: border-box;
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
html, body {
|
| 35 |
+
height: 100%;
|
| 36 |
+
font-family: 'IBM Plex Sans Arabic', sans-serif;
|
| 37 |
+
background: #000000;
|
| 38 |
+
color: #f0f2f5;
|
| 39 |
+
overflow: hidden;
|
| 40 |
+
direction: rtl;
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
.loading-screen {
|
| 44 |
+
position: fixed;
|
| 45 |
+
top: 0;
|
| 46 |
+
left: 0;
|
| 47 |
+
width: 100vw;
|
| 48 |
+
height: 100vh;
|
| 49 |
+
background: linear-gradient(45deg, #000000, #101012, #000000);
|
| 50 |
+
display: flex;
|
| 51 |
+
flex-direction: column;
|
| 52 |
+
justify-content: center;
|
| 53 |
+
align-items: center;
|
| 54 |
+
z-index: 9999;
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
.loading-logo {
|
| 58 |
+
width: 120px;
|
| 59 |
+
height: 120px;
|
| 60 |
+
position: relative;
|
| 61 |
+
margin-bottom: 40px;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.loading-orb {
|
| 65 |
+
width: 40px;
|
| 66 |
+
height: 40px;
|
| 67 |
+
background: #22d3ee;
|
| 68 |
+
border-radius: 50%;
|
| 69 |
+
position: absolute;
|
| 70 |
+
top: 50%;
|
| 71 |
+
left: 50%;
|
| 72 |
+
transform: translate(-50%, -50%);
|
| 73 |
+
box-shadow: 0 0 40px rgba(34, 211, 238, 0.8);
|
| 74 |
+
animation: pulse 2s ease-in-out infinite;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.loading-rings {
|
| 78 |
+
position: absolute;
|
| 79 |
+
top: 0;
|
| 80 |
+
left: 0;
|
| 81 |
+
width: 100%;
|
| 82 |
+
height: 100%;
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
.loading-ring {
|
| 86 |
+
position: absolute;
|
| 87 |
+
border: 2px solid #22d3ee;
|
| 88 |
+
border-radius: 50%;
|
| 89 |
+
opacity: 0.3;
|
| 90 |
+
animation: rotate 3s linear infinite;
|
| 91 |
+
}
|
| 92 |
+
|
| 93 |
+
.loading-ring:nth-child(1) {
|
| 94 |
+
width: 100%;
|
| 95 |
+
height: 100%;
|
| 96 |
+
animation-duration: 4s;
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
.loading-ring:nth-child(2) {
|
| 100 |
+
width: 80%;
|
| 101 |
+
height: 80%;
|
| 102 |
+
top: 10%;
|
| 103 |
+
left: 10%;
|
| 104 |
+
animation-duration: 3s;
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
.loading-ring:nth-child(3) {
|
| 108 |
+
width: 60%;
|
| 109 |
+
height: 60%;
|
| 110 |
+
top: 20%;
|
| 111 |
+
left: 20%;
|
| 112 |
+
animation-duration: 2s;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
.loading-text {
|
| 116 |
+
font-size: 24px;
|
| 117 |
+
font-weight: 600;
|
| 118 |
+
color: #22d3ee;
|
| 119 |
+
margin-bottom: 20px;
|
| 120 |
+
text-align: center;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
.loading-progress {
|
| 124 |
+
width: 300px;
|
| 125 |
+
height: 4px;
|
| 126 |
+
background: rgba(34, 211, 238, 0.2);
|
| 127 |
+
border-radius: 2px;
|
| 128 |
+
overflow: hidden;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
.loading-progress-bar {
|
| 132 |
+
height: 100%;
|
| 133 |
+
background: linear-gradient(90deg, #22d3ee, #0891b2);
|
| 134 |
+
border-radius: 2px;
|
| 135 |
+
animation: progress 3s ease-out forwards;
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
@keyframes pulse {
|
| 139 |
+
0%, 100% { transform: translate(-50%, -50%) scale(1); }
|
| 140 |
+
50% { transform: translate(-50%, -50%) scale(1.1); }
|
| 141 |
+
}
|
| 142 |
+
|
| 143 |
+
@keyframes rotate {
|
| 144 |
+
from { transform: rotate(0deg); }
|
| 145 |
+
to { transform: rotate(360deg); }
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
@keyframes progress {
|
| 149 |
+
from { width: 0%; }
|
| 150 |
+
to { width: 100%; }
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
.error-screen {
|
| 154 |
+
display: none;
|
| 155 |
+
position: fixed;
|
| 156 |
+
top: 0;
|
| 157 |
+
left: 0;
|
| 158 |
+
width: 100vw;
|
| 159 |
+
height: 100vh;
|
| 160 |
+
background: #000000;
|
| 161 |
+
color: #f87171;
|
| 162 |
+
display: flex;
|
| 163 |
+
flex-direction: column;
|
| 164 |
+
justify-content: center;
|
| 165 |
+
align-items: center;
|
| 166 |
+
text-align: center;
|
| 167 |
+
z-index: 10000;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
.error-title {
|
| 171 |
+
font-size: 32px;
|
| 172 |
+
font-weight: 700;
|
| 173 |
+
margin-bottom: 20px;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
.error-message {
|
| 177 |
+
font-size: 16px;
|
| 178 |
+
margin-bottom: 30px;
|
| 179 |
+
max-width: 600px;
|
| 180 |
+
line-height: 1.6;
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
.error-button {
|
| 184 |
+
padding: 12px 24px;
|
| 185 |
+
background: #f87171;
|
| 186 |
+
color: #000000;
|
| 187 |
+
border: none;
|
| 188 |
+
border-radius: 8px;
|
| 189 |
+
font-size: 14px;
|
| 190 |
+
font-weight: 600;
|
| 191 |
+
cursor: pointer;
|
| 192 |
+
}
|
| 193 |
+
</style>
|
| 194 |
+
</head>
|
| 195 |
+
<body>
|
| 196 |
+
<!-- Loading Screen -->
|
| 197 |
+
<div class="loading-screen" id="loading-screen">
|
| 198 |
+
<div class="loading-logo">
|
| 199 |
+
<div class="loading-orb"></div>
|
| 200 |
+
<div class="loading-rings">
|
| 201 |
+
<div class="loading-ring"></div>
|
| 202 |
+
<div class="loading-ring"></div>
|
| 203 |
+
<div class="loading-ring"></div>
|
| 204 |
+
</div>
|
| 205 |
+
</div>
|
| 206 |
+
<div class="loading-text">تهيئة مركز القيادة السيبراني الغامر</div>
|
| 207 |
+
<div class="loading-progress">
|
| 208 |
+
<div class="loading-progress-bar"></div>
|
| 209 |
+
</div>
|
| 210 |
+
</div>
|
| 211 |
+
|
| 212 |
+
<!-- Error Screen -->
|
| 213 |
+
<div class="error-screen" id="error-screen">
|
| 214 |
+
<div class="error-title">خطأ في التحميل</div>
|
| 215 |
+
<div class="error-message">
|
| 216 |
+
لم يتم تحميل النظام بشكل صحيح. يرجى التأكد من:
|
| 217 |
+
<br>• دعم المتصفح للرسوميات ثلاثية الأبعاد
|
| 218 |
+
• دعم WebGL
|
| 219 |
+
• اتصال الإنترنت مستقر
|
| 220 |
+
</div>
|
| 221 |
+
<button class="error-button" onclick="location.reload()">إعادة المحاولة</button>
|
| 222 |
+
</div>
|
| 223 |
+
|
| 224 |
+
<!-- Main Application Container -->
|
| 225 |
+
<div id="app-container" style="display: none;">
|
| 226 |
+
<!-- The holographic command center will be inserted here by JavaScript -->
|
| 227 |
+
</div>
|
| 228 |
+
|
| 229 |
+
<!-- System Information Panel (Hidden by default) -->
|
| 230 |
+
<div id="system-info" style="position: fixed; bottom: 10px; left: 10px; background: rgba(0,0,0,0.8); color: #22d3ee; padding: 8px 12px; border-radius: 4px; font-size: 11px; font-family: monospace; display: none; z-index: 1000;">
|
| 231 |
+
<div id="fps-counter">FPS: --</div>
|
| 232 |
+
<div id="memory-usage">Memory: -- MB</div>
|
| 233 |
+
<div id="webgl-info">WebGL: --</div>
|
| 234 |
+
</div>
|
| 235 |
+
|
| 236 |
+
<!-- Emergency Stop Button -->
|
| 237 |
+
<button id="emergency-stop-btn" onclick="window.holographicCommand?.emergencyStop()"
|
| 238 |
+
style="position: fixed; top: 20px; left: 20px; background: #f87171; color: white; border: none; border-radius: 50%; width: 60px; height: 60px; font-size: 16px; font-weight: bold; cursor: pointer; z-index: 1001; box-shadow: 0 4px 12px rgba(248, 113, 113, 0.4); display: none;">
|
| 239 |
+
🛑
|
| 240 |
+
</button>
|
| 241 |
+
|
| 242 |
+
<!-- Performance Monitor Toggle -->
|
| 243 |
+
<button id="perf-toggle" onclick="togglePerformanceMonitor()"
|
| 244 |
+
style="position: fixed; top: 20px; right: 20px; background: rgba(34, 211, 238, 0.1); color: #22d3ee; border: 1px solid #22d3ee; border-radius: 8px; padding: 8px 12px; font-size: 12px; cursor: pointer; z-index: 1001; display: none;">
|
| 245 |
+
مراقبة الأداء
|
| 246 |
+
</button>
|
| 247 |
+
|
| 248 |
+
<!-- Scripts -->
|
| 249 |
+
<script>
|
| 250 |
+
// Global error handler
|
| 251 |
+
window.addEventListener('error', (event) => {
|
| 252 |
+
console.error('خطأ في النظام:', event.error);
|
| 253 |
+
showErrorScreen();
|
| 254 |
+
});
|
| 255 |
+
|
| 256 |
+
// Performance monitoring
|
| 257 |
+
let performanceMonitor = {
|
| 258 |
+
fps: 0,
|
| 259 |
+
frameCount: 0,
|
| 260 |
+
lastTime: performance.now(),
|
| 261 |
+
|
| 262 |
+
update() {
|
| 263 |
+
this.frameCount++;
|
| 264 |
+
const currentTime = performance.now();
|
| 265 |
+
|
| 266 |
+
if (currentTime - this.lastTime >= 1000) {
|
| 267 |
+
this.fps = Math.round((this.frameCount * 1000) / (currentTime - this.lastTime));
|
| 268 |
+
this.frameCount = 0;
|
| 269 |
+
this.lastTime = currentTime;
|
| 270 |
+
this.updateDisplay();
|
| 271 |
+
}
|
| 272 |
+
},
|
| 273 |
+
|
| 274 |
+
updateDisplay() {
|
| 275 |
+
const fpsEl = document.getElementById('fps-counter');
|
| 276 |
+
if (fpsEl) {
|
| 277 |
+
fpsEl.textContent = `FPS: ${this.fps}`;
|
| 278 |
+
}
|
| 279 |
+
}
|
| 280 |
+
};
|
| 281 |
+
|
| 282 |
+
// WebGL support detection
|
| 283 |
+
function checkWebGLSupport() {
|
| 284 |
+
try {
|
| 285 |
+
const canvas = document.createElement('canvas');
|
| 286 |
+
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
| 287 |
+
return !!gl;
|
| 288 |
+
} catch (e) {
|
| 289 |
+
return false;
|
| 290 |
+
}
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
// Feature detection
|
| 294 |
+
function checkBrowserFeatures() {
|
| 295 |
+
const features = {
|
| 296 |
+
webgl: checkWebGLSupport(),
|
| 297 |
+
webxr: 'xr' in navigator,
|
| 298 |
+
webassembly: typeof WebAssembly === 'object',
|
| 299 |
+
webworkers: typeof Worker !== 'undefined',
|
| 300 |
+
mediaDevices: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia),
|
| 301 |
+
webSpeech: 'webkitSpeechRecognition' in window || 'SpeechRecognition' in window,
|
| 302 |
+
localStorage: typeof Storage !== 'undefined'
|
| 303 |
+
};
|
| 304 |
+
|
| 305 |
+
console.log('🔍 فحص ميزات المتصفح:', features);
|
| 306 |
+
return features;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
// Show error screen
|
| 310 |
+
function showErrorScreen() {
|
| 311 |
+
document.getElementById('loading-screen').style.display = 'none';
|
| 312 |
+
document.getElementById('error-screen').style.display = 'flex';
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
// Initialize system
|
| 316 |
+
async function initializeSystem() {
|
| 317 |
+
try {
|
| 318 |
+
console.log('🚀 بدء تهيئة النظام...');
|
| 319 |
+
|
| 320 |
+
// Check browser features
|
| 321 |
+
const features = checkBrowserFeatures();
|
| 322 |
+
|
| 323 |
+
if (!features.webgl) {
|
| 324 |
+
throw new Error('WebGL غير مدعوم');
|
| 325 |
+
}
|
| 326 |
+
|
| 327 |
+
// Load Three.js if not already loaded
|
| 328 |
+
if (typeof THREE === 'undefined') {
|
| 329 |
+
console.log('📦 تحميل Three.js...');
|
| 330 |
+
await loadScript('https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js');
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
// Load main application
|
| 334 |
+
console.log('📦 تحميل التطبيق الرئيسي...');
|
| 335 |
+
await loadScript('./holographic-security-command.js');
|
| 336 |
+
|
| 337 |
+
// Initialize application
|
| 338 |
+
console.log('🔧 تهيئة التطبيق...');
|
| 339 |
+
|
| 340 |
+
// Hide loading screen
|
| 341 |
+
setTimeout(() => {
|
| 342 |
+
document.getElementById('loading-screen').style.display = 'none';
|
| 343 |
+
document.getElementById('app-container').style.display = 'block';
|
| 344 |
+
document.getElementById('emergency-stop-btn').style.display = 'block';
|
| 345 |
+
document.getElementById('perf-toggle').style.display = 'block';
|
| 346 |
+
|
| 347 |
+
// Show performance monitor if in debug mode
|
| 348 |
+
if (window.location.hash.includes('debug')) {
|
| 349 |
+
document.getElementById('system-info').style.display = 'block';
|
| 350 |
+
}
|
| 351 |
+
}, 3000);
|
| 352 |
+
|
| 353 |
+
console.log('✅ تم تهيئة النظام بنجاح');
|
| 354 |
+
|
| 355 |
+
} catch (error) {
|
| 356 |
+
console.error('❌ خطأ في تهيئة النظام:', error);
|
| 357 |
+
showErrorScreen();
|
| 358 |
+
}
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
// Load script dynamically
|
| 362 |
+
function loadScript(src) {
|
| 363 |
+
return new Promise((resolve, reject) => {
|
| 364 |
+
const script = document.createElement('script');
|
| 365 |
+
script.src = src;
|
| 366 |
+
script.onload = resolve;
|
| 367 |
+
script.onerror = reject;
|
| 368 |
+
document.head.appendChild(script);
|
| 369 |
+
});
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
// Toggle performance monitor
|
| 373 |
+
function togglePerformanceMonitor() {
|
| 374 |
+
const systemInfo = document.getElementById('system-info');
|
| 375 |
+
systemInfo.style.display = systemInfo.style.display === 'none' ? 'block' : 'none';
|
| 376 |
+
}
|
| 377 |
+
|
| 378 |
+
// Memory usage monitoring
|
| 379 |
+
function updateMemoryUsage() {
|
| 380 |
+
if (performance.memory) {
|
| 381 |
+
const memoryEl = document.getElementById('memory-usage');
|
| 382 |
+
if (memoryEl) {
|
| 383 |
+
const used = Math.round(performance.memory.usedJSHeapSize / 1024 / 1024);
|
| 384 |
+
const total = Math.round(performance.memory.totalJSHeapSize / 1024 / 1024);
|
| 385 |
+
memoryEl.textContent = `Memory: ${used}/${total} MB`;
|
| 386 |
+
}
|
| 387 |
+
}
|
| 388 |
+
}
|
| 389 |
+
|
| 390 |
+
// WebGL info
|
| 391 |
+
function updateWebGLInfo() {
|
| 392 |
+
const webglEl = document.getElementById('webgl-info');
|
| 393 |
+
if (webglEl) {
|
| 394 |
+
try {
|
| 395 |
+
const canvas = document.createElement('canvas');
|
| 396 |
+
const gl = canvas.getContext('webgl');
|
| 397 |
+
if (gl) {
|
| 398 |
+
const renderer = gl.getParameter(gl.RENDERER);
|
| 399 |
+
const vendor = gl.getParameter(gl.VENDOR);
|
| 400 |
+
webglEl.textContent = `WebGL: ${renderer} (${vendor})`;
|
| 401 |
+
}
|
| 402 |
+
} catch (e) {
|
| 403 |
+
webglEl.textContent = 'WebGL: Error';
|
| 404 |
+
}
|
| 405 |
+
}
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
// Keyboard shortcuts
|
| 409 |
+
document.addEventListener('keydown', (event) => {
|
| 410 |
+
// Emergency stop (Ctrl + Shift + E)
|
| 411 |
+
if (event.ctrlKey && event.shiftKey && event.key === 'E') {
|
| 412 |
+
window.holographicCommand?.emergencyStop();
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
// Performance monitor (Ctrl + Shift + P)
|
| 416 |
+
if (event.ctrlKey && event.shiftKey && event.key === 'P') {
|
| 417 |
+
togglePerformanceMonitor();
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
// Fullscreen (F11)
|
| 421 |
+
if (event.key === 'F11') {
|
| 422 |
+
event.preventDefault();
|
| 423 |
+
if (!document.fullscreenElement) {
|
| 424 |
+
document.documentElement.requestFullscreen();
|
| 425 |
+
} else {
|
| 426 |
+
document.exitFullscreen();
|
| 427 |
+
}
|
| 428 |
+
}
|
| 429 |
+
});
|
| 430 |
+
|
| 431 |
+
// Auto-save configuration
|
| 432 |
+
function saveConfiguration() {
|
| 433 |
+
try {
|
| 434 |
+
const config = {
|
| 435 |
+
timestamp: new Date().toISOString(),
|
| 436 |
+
userAgent: navigator.userAgent,
|
| 437 |
+
screen: {
|
| 438 |
+
width: screen.width,
|
| 439 |
+
height: screen.height,
|
| 440 |
+
colorDepth: screen.colorDepth
|
| 441 |
+
},
|
| 442 |
+
viewport: {
|
| 443 |
+
width: window.innerWidth,
|
| 444 |
+
height: window.innerHeight
|
| 445 |
+
}
|
| 446 |
+
};
|
| 447 |
+
|
| 448 |
+
localStorage.setItem('holographicCommandConfig', JSON.stringify(config));
|
| 449 |
+
} catch (error) {
|
| 450 |
+
console.warn('تعذر حفظ الإعدادات:', error);
|
| 451 |
+
}
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
// Load configuration
|
| 455 |
+
function loadConfiguration() {
|
| 456 |
+
try {
|
| 457 |
+
const saved = localStorage.getItem('holographicCommandConfig');
|
| 458 |
+
if (saved) {
|
| 459 |
+
const config = JSON.parse(saved);
|
| 460 |
+
console.log('📁 تم تحميل الإعدادات المحفوظة:', config.timestamp);
|
| 461 |
+
}
|
| 462 |
+
} catch (error) {
|
| 463 |
+
console.warn('تعذر تحميل الإعدادات:', error);
|
| 464 |
+
}
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
// Initialize when DOM is ready
|
| 468 |
+
document.addEventListener('DOMContentLoaded', () => {
|
| 469 |
+
console.log('🌐 DOM جاهز، بدء التهيئة...');
|
| 470 |
+
|
| 471 |
+
loadConfiguration();
|
| 472 |
+
saveConfiguration();
|
| 473 |
+
initializeSystem();
|
| 474 |
+
|
| 475 |
+
// Update memory usage periodically
|
| 476 |
+
setInterval(updateMemoryUsage, 2000);
|
| 477 |
+
|
| 478 |
+
// Update WebGL info
|
| 479 |
+
setTimeout(updateWebGLInfo, 1000);
|
| 480 |
+
|
| 481 |
+
// Save configuration periodically
|
| 482 |
+
setInterval(saveConfiguration, 30000);
|
| 483 |
+
});
|
| 484 |
+
|
| 485 |
+
// Handle visibility changes
|
| 486 |
+
document.addEventListener('visibilitychange', () => {
|
| 487 |
+
if (document.hidden) {
|
| 488 |
+
console.log('📱 التطبيق في الخلفية');
|
| 489 |
+
} else {
|
| 490 |
+
console.log('📱 التطبيق في المقدمة');
|
| 491 |
+
updateWebGLInfo();
|
| 492 |
+
}
|
| 493 |
+
});
|
| 494 |
+
|
| 495 |
+
// Handle window focus/blur
|
| 496 |
+
window.addEventListener('focus', () => {
|
| 497 |
+
performanceMonitor.lastTime = performance.now();
|
| 498 |
+
});
|
| 499 |
+
|
| 500 |
+
// Service Worker registration for PWA
|
| 501 |
+
if ('serviceWorker' in navigator) {
|
| 502 |
+
window.addEventListener('load', () => {
|
| 503 |
+
navigator.serviceWorker.register('./sw.js')
|
| 504 |
+
.then((registration) => {
|
| 505 |
+
console.log('SW registered: ', registration);
|
| 506 |
+
})
|
| 507 |
+
.catch((registrationError) => {
|
| 508 |
+
console.log('SW registration failed: ', registrationError);
|
| 509 |
+
});
|
| 510 |
+
});
|
| 511 |
+
}
|
| 512 |
+
</script>
|
| 513 |
+
|
| 514 |
+
<!-- Progressive Web App Meta Tags -->
|
| 515 |
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
| 516 |
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
| 517 |
+
<meta name="apple-mobile-web-app-title" content="قيادة غامرة">
|
| 518 |
+
<meta name="mobile-web-app-capable" content="yes">
|
| 519 |
+
|
| 520 |
+
<!-- Open Graph Meta Tags -->
|
| 521 |
+
<meta property="og:title" content="مركز القيادة السيبراني الغامر">
|
| 522 |
+
<meta property="og:description" content="مركز قيادة سيبراني ثوري بتقنيات الواقع ��لافتراضي والمجسمات ثلاثية الأبعاد">
|
| 523 |
+
<meta property="og:type" content="website">
|
| 524 |
+
<meta property="og:image" content="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><circle cx='50' cy='50' r='40' fill='%2322d3ee'/><circle cx='50' cy='50' r='20' fill='%23000000'/><circle cx='50' cy='50' r='10' fill='%2322d3ee'/></svg>">
|
| 525 |
+
|
| 526 |
+
<!-- Twitter Card Meta Tags -->
|
| 527 |
+
<meta name="twitter:card" content="summary_large_image">
|
| 528 |
+
<meta name="twitter:title" content="مركز القيادة السيبراني الغامر">
|
| 529 |
+
<meta name="twitter:description" content="مركز قيادة سيبراني ثوري بتقنيات متقدمة">
|
| 530 |
+
<meta name="twitter:image" content="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><circle cx='50' cy='50' r='40' fill='%2322d3ee'/><circle cx='50' cy='50' r='20' fill='%23000000'/><circle cx='50' cy='50' r='10' fill='%2322d3ee'/></svg>">
|
| 531 |
+
</head>
|
| 532 |
+
<body>
|
| 533 |
+
</body>
|
| 534 |
+
</html>
|
holographic-security-command.js
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
imgs/browser_security_0.png
ADDED
|
imgs/browser_security_6.png
ADDED
|
Git LFS Details
|
imgs/browser_security_8.png
ADDED
|
Git LFS Details
|
imgs/csp_code_3.png
ADDED
|
Git LFS Details
|
imgs/csp_code_7.jpg
ADDED
|
Git LFS Details
|
imgs/csp_code_8.axd
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6c2b22cbf657b3e5f4dbfd669f903140e4a8eee74a723dca70e25013fc58357e
|
| 3 |
+
size 783040
|
imgs/cyber_threats_0.png
ADDED
|
imgs/cyber_threats_2.jpg
ADDED
|
Git LFS Details
|
imgs/cyber_threats_9.jpg
ADDED
|
imgs/data_protection_1.jpeg
ADDED
|
Git LFS Details
|
imgs/data_protection_3.png
ADDED
|
imgs/data_protection_5.jpg
ADDED
|
Git LFS Details
|
imgs/image_meta.json
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
{
|
| 3 |
+
"query": "صورة توضيحية لجدار الحماية WAF لحماية التطبيقات",
|
| 4 |
+
"image_info": {
|
| 5 |
+
"url": "https://www.radware.com/RadwareSite/MediaLibraries/Images/Cyberpedia/what-is-waf.jpg",
|
| 6 |
+
"img_format": "JPEG",
|
| 7 |
+
"mode": "RGB",
|
| 8 |
+
"file_size": 75946,
|
| 9 |
+
"width": 1100,
|
| 10 |
+
"height": 575,
|
| 11 |
+
"total_pixels": 632500,
|
| 12 |
+
"basic_score": 0.8806756916264162,
|
| 13 |
+
"file_name": "waf_protection_7.jpg"
|
| 14 |
+
},
|
| 15 |
+
"llm_score": null
|
| 16 |
+
},
|
| 17 |
+
{
|
| 18 |
+
"query": "صورة توضيحية لجدار الحماية WAF لحماية التطبيقات",
|
| 19 |
+
"image_info": {
|
| 20 |
+
"url": "https://www.cloudflare.com/img/learning/ddos/glossary/waf/waf.png",
|
| 21 |
+
"img_format": "PNG",
|
| 22 |
+
"mode": "RGB",
|
| 23 |
+
"file_size": 43429,
|
| 24 |
+
"width": 1459,
|
| 25 |
+
"height": 660,
|
| 26 |
+
"total_pixels": 962940,
|
| 27 |
+
"basic_score": 0.8791460663025104,
|
| 28 |
+
"file_name": "waf_protection_0.png"
|
| 29 |
+
},
|
| 30 |
+
"llm_score": null
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"query": "صورة توضيحية لجدار الحماية WAF لحماية التطبيقات",
|
| 34 |
+
"image_info": {
|
| 35 |
+
"url": "https://www.cisco.com/content/dam/cisco-cdc/site/images/heroes/products/security/web-application-firewall-724x543.png",
|
| 36 |
+
"img_format": "PNG",
|
| 37 |
+
"mode": "RGB",
|
| 38 |
+
"file_size": 30138,
|
| 39 |
+
"width": 724,
|
| 40 |
+
"height": 543,
|
| 41 |
+
"total_pixels": 393132,
|
| 42 |
+
"basic_score": 0.8071207524844679,
|
| 43 |
+
"file_name": "waf_protection_5.png"
|
| 44 |
+
},
|
| 45 |
+
"llm_score": null
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"query": "صورة توضيحية لمتصفح الويب وأمان الشبكة",
|
| 49 |
+
"image_info": {
|
| 50 |
+
"url": "https://zigrin.com/wp-content/uploads/2022/08/http-security-headers-1-1024x933.png",
|
| 51 |
+
"img_format": "PNG",
|
| 52 |
+
"mode": "RGBA",
|
| 53 |
+
"file_size": 225549,
|
| 54 |
+
"width": 1024,
|
| 55 |
+
"height": 933,
|
| 56 |
+
"total_pixels": 955392,
|
| 57 |
+
"basic_score": 0.9279848464595593,
|
| 58 |
+
"file_name": "browser_security_6.png"
|
| 59 |
+
},
|
| 60 |
+
"llm_score": null
|
| 61 |
+
},
|
| 62 |
+
{
|
| 63 |
+
"query": "صورة توضيحية لمتصفح الويب وأمان الشبكة",
|
| 64 |
+
"image_info": {
|
| 65 |
+
"url": "https://blogadmin.detectify.com/app/uploads/2019/02/chrome_2019-02-01_11-11-13-1.png",
|
| 66 |
+
"img_format": "PNG",
|
| 67 |
+
"mode": "RGBA",
|
| 68 |
+
"file_size": 107044,
|
| 69 |
+
"width": 1071,
|
| 70 |
+
"height": 675,
|
| 71 |
+
"total_pixels": 722925,
|
| 72 |
+
"basic_score": 0.8959063212373346,
|
| 73 |
+
"file_name": "browser_security_8.png"
|
| 74 |
+
},
|
| 75 |
+
"llm_score": null
|
| 76 |
+
},
|
| 77 |
+
{
|
| 78 |
+
"query": "صورة توضيحية لمتصفح الويب وأمان الشبكة",
|
| 79 |
+
"image_info": {
|
| 80 |
+
"url": "https://blogadmin.detectify.com/app/uploads/2019/02/without-XCTO-1.png",
|
| 81 |
+
"img_format": "PNG",
|
| 82 |
+
"mode": "RGBA",
|
| 83 |
+
"file_size": 75280,
|
| 84 |
+
"width": 1071,
|
| 85 |
+
"height": 675,
|
| 86 |
+
"total_pixels": 722925,
|
| 87 |
+
"basic_score": 0.8925626304714731,
|
| 88 |
+
"file_name": "browser_security_0.png"
|
| 89 |
+
},
|
| 90 |
+
"llm_score": null
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"query": "صورة توضيحية لكود تنفيذ سياسة أمان المحتوى",
|
| 94 |
+
"image_info": {
|
| 95 |
+
"url": "https://www.alliancetek.com/blog/image.axd?picture=2023%2F4%2F319.+Content+Security+Policy+(CSP)+%26+its+Importance.png",
|
| 96 |
+
"img_format": "PNG",
|
| 97 |
+
"mode": "RGBA",
|
| 98 |
+
"file_size": 783040,
|
| 99 |
+
"width": 1200,
|
| 100 |
+
"height": 630,
|
| 101 |
+
"total_pixels": 756000,
|
| 102 |
+
"basic_score": 0.9371562827052231,
|
| 103 |
+
"file_name": "csp_code_8.axd"
|
| 104 |
+
},
|
| 105 |
+
"llm_score": null
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"query": "صورة توضيحية لكود تنفيذ سياسة أمان المحتوى",
|
| 109 |
+
"image_info": {
|
| 110 |
+
"url": "https://media.licdn.com/dms/image/v2/D4E12AQGLjtJ6wso4Mw/article-cover_image-shrink_720_1280/article-cover_image-shrink_720_1280/0/1722195376458?e=2147483647&v=beta&t=FMd0-zZ1QfnResxrLh3MrGCFZrqZPJSgKk_U6yggw-A",
|
| 111 |
+
"img_format": "PNG",
|
| 112 |
+
"mode": "RGB",
|
| 113 |
+
"file_size": 350709,
|
| 114 |
+
"width": 1163,
|
| 115 |
+
"height": 720,
|
| 116 |
+
"total_pixels": 837360,
|
| 117 |
+
"basic_score": 0.9318756482583167,
|
| 118 |
+
"file_name": "csp_code_7.jpg"
|
| 119 |
+
},
|
| 120 |
+
"llm_score": null
|
| 121 |
+
},
|
| 122 |
+
{
|
| 123 |
+
"query": "صورة توضيحية لكود تنفيذ سياسة أمان المحتوى",
|
| 124 |
+
"image_info": {
|
| 125 |
+
"url": "https://miro.medium.com/v2/resize:fit:1400/1*8qFV9qv7QHdPdjlrY5zuVw.png",
|
| 126 |
+
"img_format": "PNG",
|
| 127 |
+
"mode": "RGB",
|
| 128 |
+
"file_size": 129469,
|
| 129 |
+
"width": 1400,
|
| 130 |
+
"height": 708,
|
| 131 |
+
"total_pixels": 991200,
|
| 132 |
+
"basic_score": 0.9139329365579216,
|
| 133 |
+
"file_name": "csp_code_3.png"
|
| 134 |
+
},
|
| 135 |
+
"llm_score": null
|
| 136 |
+
},
|
| 137 |
+
{
|
| 138 |
+
"query": "صورة توضيحية للتهديدات السيبرانية والحماية التقنية",
|
| 139 |
+
"image_info": {
|
| 140 |
+
"url": "https://marvel-b1-cdn.bc0a.com/f00000000310757/www.fortinet.com/content/dam/fortinet/images/cyberglossary/types-of-cyberattacks.png",
|
| 141 |
+
"img_format": "PNG",
|
| 142 |
+
"mode": "P",
|
| 143 |
+
"file_size": 49451,
|
| 144 |
+
"width": 978,
|
| 145 |
+
"height": 641,
|
| 146 |
+
"total_pixels": 626898,
|
| 147 |
+
"basic_score": 0.8727671442538397,
|
| 148 |
+
"file_name": "cyber_threats_0.png"
|
| 149 |
+
},
|
| 150 |
+
"llm_score": null
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
"query": "صورة توضيحية للتهديدات السيبرانية والحماية التقنية",
|
| 154 |
+
"image_info": {
|
| 155 |
+
"url": "https://www.stealthlabs.com/wp-content/uploads/2020/12/cybersecurity-best-practices-to-protect-from-cyber-threats.jpg",
|
| 156 |
+
"img_format": "JPEG",
|
| 157 |
+
"mode": "RGB",
|
| 158 |
+
"file_size": 89374,
|
| 159 |
+
"width": 700,
|
| 160 |
+
"height": 482,
|
| 161 |
+
"total_pixels": 337400,
|
| 162 |
+
"basic_score": 0.805662638756518,
|
| 163 |
+
"file_name": "cyber_threats_9.jpg"
|
| 164 |
+
},
|
| 165 |
+
"llm_score": null
|
| 166 |
+
},
|
| 167 |
+
{
|
| 168 |
+
"query": "صورة توضيحية للتهديدات السيبرانية والحماية التقنية",
|
| 169 |
+
"image_info": {
|
| 170 |
+
"url": "https://geeks.co.uk/wp-content/uploads/2019/03/CG_Infographic_V02.jpg",
|
| 171 |
+
"img_format": "JPEG",
|
| 172 |
+
"mode": "RGB",
|
| 173 |
+
"file_size": 357580,
|
| 174 |
+
"width": 1920,
|
| 175 |
+
"height": 1080,
|
| 176 |
+
"total_pixels": 2073600,
|
| 177 |
+
"basic_score": 0.7364495733696163,
|
| 178 |
+
"file_name": "cyber_threats_2.jpg"
|
| 179 |
+
},
|
| 180 |
+
"llm_score": null
|
| 181 |
+
},
|
| 182 |
+
{
|
| 183 |
+
"query": "صورة توضيحية لهجمات XSS وطرق منعها",
|
| 184 |
+
"image_info": {
|
| 185 |
+
"url": "https://media.geeksforgeeks.org/wp-content/uploads/20190516152959/Cross-Site-ScriptingXSS.png",
|
| 186 |
+
"img_format": "PNG",
|
| 187 |
+
"mode": "RGB",
|
| 188 |
+
"file_size": 105535,
|
| 189 |
+
"width": 1200,
|
| 190 |
+
"height": 737,
|
| 191 |
+
"total_pixels": 884400,
|
| 192 |
+
"basic_score": 0.9141755326862075,
|
| 193 |
+
"file_name": "xss_prevention_3.png"
|
| 194 |
+
},
|
| 195 |
+
"llm_score": null
|
| 196 |
+
},
|
| 197 |
+
{
|
| 198 |
+
"query": "صورة توضيحية لهجمات XSS وطرق منعها",
|
| 199 |
+
"image_info": {
|
| 200 |
+
"url": "https://marvel-b1-cdn.bc0a.com/f00000000310757/www.fortinet.com/content/dam/fortinet/images/cyberglossary/xss.jpg",
|
| 201 |
+
"img_format": "JPEG",
|
| 202 |
+
"mode": "RGB",
|
| 203 |
+
"file_size": 64949,
|
| 204 |
+
"width": 978,
|
| 205 |
+
"height": 640,
|
| 206 |
+
"total_pixels": 625920,
|
| 207 |
+
"basic_score": 0.8842432575862873,
|
| 208 |
+
"file_name": "xss_prevention_6.jpg"
|
| 209 |
+
},
|
| 210 |
+
"llm_score": null
|
| 211 |
+
},
|
| 212 |
+
{
|
| 213 |
+
"query": "صورة توضيحية لهجمات XSS وطرق منعها",
|
| 214 |
+
"image_info": {
|
| 215 |
+
"url": "https://www.vmware.com/media/blt8c9a8aaca0ffd4ac/blt5255a8008be895b9/66d06a18f6c3d10f63f287f2/cross-site-scripting-diagram.png",
|
| 216 |
+
"img_format": "PNG",
|
| 217 |
+
"mode": "P",
|
| 218 |
+
"file_size": 12255,
|
| 219 |
+
"width": 863,
|
| 220 |
+
"height": 487,
|
| 221 |
+
"total_pixels": 420281,
|
| 222 |
+
"basic_score": 0.8124413701460721,
|
| 223 |
+
"file_name": "xss_prevention_9.png"
|
| 224 |
+
},
|
| 225 |
+
"llm_score": null
|
| 226 |
+
},
|
| 227 |
+
{
|
| 228 |
+
"query": "صورة توضيحية للـ Trusted Types في تطوير الويب الآمن",
|
| 229 |
+
"image_info": {
|
| 230 |
+
"url": "https://images.ctfassets.net/23aumh6u8s0i/5gieAxw4n3rxYsyjaAnhGm/aa67599b991ad67b3241bf730fc2a131/security_programming_hero.jpg",
|
| 231 |
+
"img_format": "JPEG",
|
| 232 |
+
"mode": "RGB",
|
| 233 |
+
"file_size": 383308,
|
| 234 |
+
"width": 1178,
|
| 235 |
+
"height": 1056,
|
| 236 |
+
"total_pixels": 1243968,
|
| 237 |
+
"basic_score": 0.9355656918468983,
|
| 238 |
+
"file_name": "trusted_types_7.jpg"
|
| 239 |
+
},
|
| 240 |
+
"llm_score": null
|
| 241 |
+
},
|
| 242 |
+
{
|
| 243 |
+
"query": "صورة توضيحية للـ Trusted Types في تطوير الويب الآمن",
|
| 244 |
+
"image_info": {
|
| 245 |
+
"url": "https://media2.dev.to/dynamic/image/width=1080,height=1080,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn7cc0flqtbe919kg7qrk.png",
|
| 246 |
+
"img_format": "WEBP",
|
| 247 |
+
"mode": "RGB",
|
| 248 |
+
"file_size": 115914,
|
| 249 |
+
"width": 1080,
|
| 250 |
+
"height": 1080,
|
| 251 |
+
"total_pixels": 1166400,
|
| 252 |
+
"basic_score": 0.9317617343491739,
|
| 253 |
+
"file_name": "trusted_types_0.png"
|
| 254 |
+
},
|
| 255 |
+
"llm_score": null
|
| 256 |
+
},
|
| 257 |
+
{
|
| 258 |
+
"query": "صورة توضيحية للـ Trusted Types في تطوير الويب الآمن",
|
| 259 |
+
"image_info": {
|
| 260 |
+
"url": "https://andrewlock.net/content/images/2025/trusted_types_banner.png",
|
| 261 |
+
"img_format": "PNG",
|
| 262 |
+
"mode": "P",
|
| 263 |
+
"file_size": 20404,
|
| 264 |
+
"width": 1200,
|
| 265 |
+
"height": 800,
|
| 266 |
+
"total_pixels": 960000,
|
| 267 |
+
"basic_score": 0.9149369468078001,
|
| 268 |
+
"file_name": "trusted_types_3.png"
|
| 269 |
+
},
|
| 270 |
+
"llm_score": null
|
| 271 |
+
},
|
| 272 |
+
{
|
| 273 |
+
"query": "صورة توضيحية لرمز الحماية والأمان السيبراني لمشروع أمان المحتوى",
|
| 274 |
+
"image_info": {
|
| 275 |
+
"url": "https://www.alliancetek.com/blog/image.axd?picture=2023%2F4%2F319.+Content+Security+Policy+(CSP)+%26+its+Importance.png",
|
| 276 |
+
"img_format": "PNG",
|
| 277 |
+
"mode": "RGBA",
|
| 278 |
+
"file_size": 783040,
|
| 279 |
+
"width": 1200,
|
| 280 |
+
"height": 630,
|
| 281 |
+
"total_pixels": 756000,
|
| 282 |
+
"basic_score": 0.9371562827052231,
|
| 283 |
+
"file_name": "security_shield_1.axd"
|
| 284 |
+
},
|
| 285 |
+
"llm_score": null
|
| 286 |
+
},
|
| 287 |
+
{
|
| 288 |
+
"query": "صورة توضيحية لرمز الحماية والأمان السيبراني لمشروع أمان المحتوى",
|
| 289 |
+
"image_info": {
|
| 290 |
+
"url": "https://protocolguard.com/resources/wp-content/uploads/2023/11/Content-Security-Policy-CSP-HTTP-Header-Explained.webp",
|
| 291 |
+
"img_format": "WEBP",
|
| 292 |
+
"mode": "RGB",
|
| 293 |
+
"file_size": 64060,
|
| 294 |
+
"width": 1200,
|
| 295 |
+
"height": 628,
|
| 296 |
+
"total_pixels": 753600,
|
| 297 |
+
"basic_score": 0.9120299095297689,
|
| 298 |
+
"file_name": "security_shield_4.webp"
|
| 299 |
+
},
|
| 300 |
+
"llm_score": null
|
| 301 |
+
},
|
| 302 |
+
{
|
| 303 |
+
"query": "صورة توضيحية لرمز الحماية والأمان السيبراني لمشروع أمان المحتوى",
|
| 304 |
+
"image_info": {
|
| 305 |
+
"url": "https://eloquent-festival-6ad5e31a6a.media.strapiapp.com/what_is_csp_29b528191f.png",
|
| 306 |
+
"img_format": "PNG",
|
| 307 |
+
"mode": "P",
|
| 308 |
+
"file_size": 29863,
|
| 309 |
+
"width": 816,
|
| 310 |
+
"height": 1056,
|
| 311 |
+
"total_pixels": 861696,
|
| 312 |
+
"basic_score": 0.8905223346879828,
|
| 313 |
+
"file_name": "security_shield_2.png"
|
| 314 |
+
},
|
| 315 |
+
"llm_score": null
|
| 316 |
+
},
|
| 317 |
+
{
|
| 318 |
+
"query": "صورة توضيحية لشهادة SSL/HTTPS وأمان الويب",
|
| 319 |
+
"image_info": {
|
| 320 |
+
"url": "https://www.itarian.com/blog/wp-content/uploads/2025/06/what-is-ssl.png",
|
| 321 |
+
"img_format": "PNG",
|
| 322 |
+
"mode": "RGB",
|
| 323 |
+
"file_size": 1784371,
|
| 324 |
+
"width": 1536,
|
| 325 |
+
"height": 1024,
|
| 326 |
+
"total_pixels": 1572864,
|
| 327 |
+
"basic_score": 0.8232661634718084,
|
| 328 |
+
"file_name": "ssl_security_5.png"
|
| 329 |
+
},
|
| 330 |
+
"llm_score": null
|
| 331 |
+
},
|
| 332 |
+
{
|
| 333 |
+
"query": "صورة توضيحية لشهادة SSL/HTTPS وأمان الويب",
|
| 334 |
+
"image_info": {
|
| 335 |
+
"url": "https://websitedepot.com/wp-content/uploads/2017/09/What-is-an-SSL-Certificate-and-how-does-It-Work.jpg",
|
| 336 |
+
"img_format": "JPEG",
|
| 337 |
+
"mode": "RGB",
|
| 338 |
+
"file_size": 78381,
|
| 339 |
+
"width": 800,
|
| 340 |
+
"height": 460,
|
| 341 |
+
"total_pixels": 368000,
|
| 342 |
+
"basic_score": 0.81395921257584,
|
| 343 |
+
"file_name": "ssl_security_7.jpg"
|
| 344 |
+
},
|
| 345 |
+
"llm_score": null
|
| 346 |
+
},
|
| 347 |
+
{
|
| 348 |
+
"query": "صورة توضيحية لشهادة SSL/HTTPS وأمان الويب",
|
| 349 |
+
"image_info": {
|
| 350 |
+
"url": "https://media.geeksforgeeks.org/wp-content/uploads/20250801143329769220/what_is_ssl_certificate_.webp",
|
| 351 |
+
"img_format": "WEBP",
|
| 352 |
+
"mode": "RGB",
|
| 353 |
+
"file_size": 14448,
|
| 354 |
+
"width": 800,
|
| 355 |
+
"height": 400,
|
| 356 |
+
"total_pixels": 320000,
|
| 357 |
+
"basic_score": 0.7871795758910557,
|
| 358 |
+
"file_name": "ssl_security_8.webp"
|
| 359 |
+
},
|
| 360 |
+
"llm_score": null
|
| 361 |
+
},
|
| 362 |
+
{
|
| 363 |
+
"query": "صورة توضيحية لحماية البيانات والخصوصية الرقمية",
|
| 364 |
+
"image_info": {
|
| 365 |
+
"url": "https://virtualcyberlabs.com/wp-content/uploads/2023/11/Data-Privacy.jpg",
|
| 366 |
+
"img_format": "JPEG",
|
| 367 |
+
"mode": "RGB",
|
| 368 |
+
"file_size": 138276,
|
| 369 |
+
"width": 1200,
|
| 370 |
+
"height": 800,
|
| 371 |
+
"total_pixels": 960000,
|
| 372 |
+
"basic_score": 0.9367964970733705,
|
| 373 |
+
"file_name": "data_protection_5.jpg"
|
| 374 |
+
},
|
| 375 |
+
"llm_score": null
|
| 376 |
+
},
|
| 377 |
+
{
|
| 378 |
+
"query": "صورة توضيحية لحماية البيانات والخصوصية الرقمية",
|
| 379 |
+
"image_info": {
|
| 380 |
+
"url": "https://d2nzy1qhita6w.cloudfront.net/media/magefan_blog/data-privacy-IT-security-protection.jpeg",
|
| 381 |
+
"img_format": "JPEG",
|
| 382 |
+
"mode": "RGB",
|
| 383 |
+
"file_size": 271609,
|
| 384 |
+
"width": 1200,
|
| 385 |
+
"height": 669,
|
| 386 |
+
"total_pixels": 802800,
|
| 387 |
+
"basic_score": 0.9342512061750423,
|
| 388 |
+
"file_name": "data_protection_1.jpeg"
|
| 389 |
+
},
|
| 390 |
+
"llm_score": null
|
| 391 |
+
},
|
| 392 |
+
{
|
| 393 |
+
"query": "صورة توضيحية لحماية البيانات والخصوصية الرقمية",
|
| 394 |
+
"image_info": {
|
| 395 |
+
"url": "https://dataprivacymanager.net/wp-content/uploads/2020/08/visual-representation-of-data-privacy-and-data-security-areas.png",
|
| 396 |
+
"img_format": "PNG",
|
| 397 |
+
"mode": "RGBA",
|
| 398 |
+
"file_size": 54346,
|
| 399 |
+
"width": 1200,
|
| 400 |
+
"height": 628,
|
| 401 |
+
"total_pixels": 753600,
|
| 402 |
+
"basic_score": 0.8909886570752481,
|
| 403 |
+
"file_name": "data_protection_3.png"
|
| 404 |
+
},
|
| 405 |
+
"llm_score": null
|
| 406 |
+
},
|
| 407 |
+
{
|
| 408 |
+
"query": "صورة توضيحية لعنوان HTTP وأمان التطبيق الويب الحديث",
|
| 409 |
+
"image_info": {
|
| 410 |
+
"url": "https://zigrin.com/wp-content/uploads/2022/08/http-security-headers-1-1024x933.png",
|
| 411 |
+
"img_format": "PNG",
|
| 412 |
+
"mode": "RGBA",
|
| 413 |
+
"file_size": 225549,
|
| 414 |
+
"width": 1024,
|
| 415 |
+
"height": 933,
|
| 416 |
+
"total_pixels": 955392,
|
| 417 |
+
"basic_score": 0.9279848464595593,
|
| 418 |
+
"file_name": "web_security_0.png"
|
| 419 |
+
},
|
| 420 |
+
"llm_score": null
|
| 421 |
+
},
|
| 422 |
+
{
|
| 423 |
+
"query": "صورة توضيحية لعنوان HTTP وأمان التطبيق الويب الحديث",
|
| 424 |
+
"image_info": {
|
| 425 |
+
"url": "https://blogadmin.detectify.com/app/uploads/2019/02/without-XCTO-1.png",
|
| 426 |
+
"img_format": "PNG",
|
| 427 |
+
"mode": "RGBA",
|
| 428 |
+
"file_size": 75280,
|
| 429 |
+
"width": 1071,
|
| 430 |
+
"height": 675,
|
| 431 |
+
"total_pixels": 722925,
|
| 432 |
+
"basic_score": 0.8925626304714731,
|
| 433 |
+
"file_name": "web_security_8.png"
|
| 434 |
+
},
|
| 435 |
+
"llm_score": null
|
| 436 |
+
},
|
| 437 |
+
{
|
| 438 |
+
"query": "صورة توضيحية لعنوان HTTP وأمان التطبيق الويب الحديث",
|
| 439 |
+
"image_info": {
|
| 440 |
+
"url": "https://blog.pixelfreestudio.com/wp-content/uploads/2024/08/f5d0fb3690616e22c43894d44cf9165d_1645695339-1024x576.jpg",
|
| 441 |
+
"img_format": "JPEG",
|
| 442 |
+
"mode": "RGB",
|
| 443 |
+
"file_size": 43244,
|
| 444 |
+
"width": 1024,
|
| 445 |
+
"height": 576,
|
| 446 |
+
"total_pixels": 589824,
|
| 447 |
+
"basic_score": 0.8728681649193576,
|
| 448 |
+
"file_name": "web_security_4.jpg"
|
| 449 |
+
},
|
| 450 |
+
"llm_score": null
|
| 451 |
+
}
|
| 452 |
+
]
|
imgs/security_shield_1.axd
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6c2b22cbf657b3e5f4dbfd669f903140e4a8eee74a723dca70e25013fc58357e
|
| 3 |
+
size 783040
|
imgs/security_shield_2.png
ADDED
|
imgs/security_shield_4.webp
ADDED
|
imgs/ssl_security_5.png
ADDED
|
Git LFS Details
|
imgs/ssl_security_7.jpg
ADDED
|
imgs/ssl_security_8.webp
ADDED
|
imgs/trusted_types_0.png
ADDED
|
Git LFS Details
|
imgs/trusted_types_3.png
ADDED
|
imgs/trusted_types_7.jpg
ADDED
|
Git LFS Details
|
imgs/waf_protection_0.png
ADDED
|
imgs/waf_protection_5.png
ADDED
|
imgs/waf_protection_7.jpg
ADDED
|
imgs/web_security_0.png
ADDED
|
Git LFS Details
|
imgs/web_security_4.jpg
ADDED
|
imgs/web_security_8.png
ADDED
|
imgs/xss_prevention_3.png
ADDED
|
Git LFS Details
|
imgs/xss_prevention_6.jpg
ADDED
|
imgs/xss_prevention_9.png
ADDED
|
index.html
ADDED
|
@@ -0,0 +1,878 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<!DOCTYPE html>
|
| 2 |
+
<html lang="ar" dir="rtl">
|
| 3 |
+
<head>
|
| 4 |
+
<meta charset="UTF-8">
|
| 5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>مشروع سياسة أمان المحتوى - أحدث التقنيات 2025</title>
|
| 7 |
+
<meta name="description" content="دليل شامل لسياسة أمان المحتوى (CSP) بأحدث التقنيات في 2025 مع أمثلة عملية وأدوات تفاعلية">
|
| 8 |
+
|
| 9 |
+
<!-- Fonts -->
|
| 10 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 11 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
| 12 |
+
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
| 13 |
+
|
| 14 |
+
<!-- Icons -->
|
| 15 |
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/heroicons@2.0.0/24/outline/index.css">
|
| 16 |
+
|
| 17 |
+
<!-- Styles -->
|
| 18 |
+
<link rel="stylesheet" href="styles/main.css">
|
| 19 |
+
<link rel="stylesheet" href="styles/components.css">
|
| 20 |
+
<link rel="stylesheet" href="styles/responsive.css">
|
| 21 |
+
</head>
|
| 22 |
+
<body>
|
| 23 |
+
<!-- Navigation -->
|
| 24 |
+
<nav class="navbar">
|
| 25 |
+
<div class="nav-container">
|
| 26 |
+
<div class="nav-brand">
|
| 27 |
+
<svg class="nav-icon" viewBox="0 0 24 24" fill="currentColor">
|
| 28 |
+
<path d="M12 2L2 7v10c0 5.55 3.84 9.739 9 11 5.16-1.261 9-5.45 9-11V7l-10-5z"/>
|
| 29 |
+
</svg>
|
| 30 |
+
<span>أمان المحتوى</span>
|
| 31 |
+
</div>
|
| 32 |
+
|
| 33 |
+
<div class="nav-links">
|
| 34 |
+
<a href="#hero" class="nav-link">الرئيسية</a>
|
| 35 |
+
<a href="#guide" class="nav-link">الدليل</a>
|
| 36 |
+
<a href="#examples" class="nav-link">أمثلة عملية</a>
|
| 37 |
+
<a href="#tools" class="nav-link">الأدوات</a>
|
| 38 |
+
<a href="#technologies" class="nav-link">التقنيات الحديثة</a>
|
| 39 |
+
</div>
|
| 40 |
+
|
| 41 |
+
<div class="nav-toggle">
|
| 42 |
+
<span></span>
|
| 43 |
+
<span></span>
|
| 44 |
+
<span></span>
|
| 45 |
+
</div>
|
| 46 |
+
</div>
|
| 47 |
+
</nav>
|
| 48 |
+
|
| 49 |
+
<!-- Hero Section -->
|
| 50 |
+
<section id="hero" class="hero">
|
| 51 |
+
<div class="hero-video">
|
| 52 |
+
<video autoplay muted loop playsinline>
|
| 53 |
+
<source src="data:video/mp4;base64," type="video/mp4">
|
| 54 |
+
<!-- Fallback gradient background -->
|
| 55 |
+
</video>
|
| 56 |
+
</div>
|
| 57 |
+
|
| 58 |
+
<div class="hero-content">
|
| 59 |
+
<div class="hero-badge">
|
| 60 |
+
<span>🚀 أحدث التقنيات 2025</span>
|
| 61 |
+
</div>
|
| 62 |
+
|
| 63 |
+
<h1 class="hero-title">
|
| 64 |
+
مشروع سياسة أمان المحتوى
|
| 65 |
+
<span class="hero-subtitle">Content Security Policy</span>
|
| 66 |
+
</h1>
|
| 67 |
+
|
| 68 |
+
<p class="hero-description">
|
| 69 |
+
دليل شامل لأحدث تقنيات حماية تطبيقات الويب من خلال سياسة أمان المحتوى المتقدمة،
|
| 70 |
+
مع أمثلة عملية وأدوات تفاعلية لتطبيق أفضل الممارسات الأمنية في 2025
|
| 71 |
+
</p>
|
| 72 |
+
|
| 73 |
+
<div class="hero-actions">
|
| 74 |
+
<button class="btn btn-primary" onclick="scrollToSection('guide')">
|
| 75 |
+
<svg class="btn-icon" viewBox="0 0 24 24" fill="currentColor">
|
| 76 |
+
<path d="M13 5l7 7-7 7M5 5h8v2H7v10h6v2H5z"/>
|
| 77 |
+
</svg>
|
| 78 |
+
ابدأ التعلم
|
| 79 |
+
</button>
|
| 80 |
+
|
| 81 |
+
<button class="btn btn-secondary" onclick="scrollToSection('tools')">
|
| 82 |
+
<svg class="btn-icon" viewBox="0 0 24 24" fill="currentColor">
|
| 83 |
+
<path d="M19.14,12.94C19.18,12.64 19.2,12.31 19.2,12C19.2,11.69 19.18,11.36 19.14,11.06L21.16,9.48C21.34,9.33 21.39,9.09 21.35,8.87L19.96,5.55C19.87,5.15 19.58,4.84 19.15,4.72L16.38,4.06C15.87,3.92 15.35,4.05 14.94,4.43L13.12,6.09C12.8,5.91 12.45,5.79 12.08,5.75L11.73,2.42C11.64,1.96 11.29,1.59 10.82,1.49L8.05,0.83C7.57,0.72 7.06,0.85 6.66,1.2L4.84,2.86C4.43,3.23 4.22,3.76 4.26,4.3L4.95,8.13C4.99,8.47 4.96,8.81 4.86,9.12L2.84,10.7C2.66,10.85 2.61,11.09 2.65,11.31L4.04,14.63C4.13,15.03 4.42,15.34 4.85,15.46L7.62,16.12C8.13,16.26 8.65,16.13 9.06,15.75L10.88,14.09C11.2,14.27 11.55,14.39 11.92,14.43L12.27,17.76C12.36,18.22 12.71,18.59 13.18,18.69L15.95,19.35C16.43,19.46 16.94,19.33 17.34,18.98L19.16,17.32C19.57,16.95 19.78,16.42 19.74,15.88L19.14,12.94Z"/>
|
| 84 |
+
</svg>
|
| 85 |
+
الأدوات التفاعلية
|
| 86 |
+
</button>
|
| 87 |
+
</div>
|
| 88 |
+
|
| 89 |
+
<div class="hero-stats">
|
| 90 |
+
<div class="stat">
|
| 91 |
+
<span class="stat-number">100%</span>
|
| 92 |
+
<span class="stat-label">حماية من XSS</span>
|
| 93 |
+
</div>
|
| 94 |
+
<div class="stat">
|
| 95 |
+
<span class="stat-number">2025</span>
|
| 96 |
+
<span class="stat-label">تقنيات حديثة</span>
|
| 97 |
+
</div>
|
| 98 |
+
<div class="stat">
|
| 99 |
+
<span class="stat-number">50+</span>
|
| 100 |
+
<span class="stat-label">مثال عملي</span>
|
| 101 |
+
</div>
|
| 102 |
+
</div>
|
| 103 |
+
</div>
|
| 104 |
+
|
| 105 |
+
<div class="hero-visual">
|
| 106 |
+
<img src="imgs/security_shield_1.axd" alt="أمان المحتوى" class="hero-image">
|
| 107 |
+
</div>
|
| 108 |
+
</section>
|
| 109 |
+
|
| 110 |
+
<!-- Guide Section -->
|
| 111 |
+
<section id="guide" class="guide">
|
| 112 |
+
<div class="container">
|
| 113 |
+
<div class="section-header">
|
| 114 |
+
<h2 class="section-title">دليل شامل لسياسة أمان المحتوى</h2>
|
| 115 |
+
<p class="section-description">
|
| 116 |
+
تعلم أساسيات CSP وأحدث التقنيات في حماية تطبيقات الويب من التهديدات السيبرانية
|
| 117 |
+
</p>
|
| 118 |
+
</div>
|
| 119 |
+
|
| 120 |
+
<div class="guide-grid">
|
| 121 |
+
<!-- CSP Fundamentals -->
|
| 122 |
+
<div class="guide-card">
|
| 123 |
+
<div class="card-icon">
|
| 124 |
+
<img src="imgs/web_security_0.png" alt="أمن الويب" class="icon-image">
|
| 125 |
+
</div>
|
| 126 |
+
<h3 class="card-title">أساسيات CSP</h3>
|
| 127 |
+
<p class="card-description">
|
| 128 |
+
فهم مبادئ سياسة أمان المحتوى وكيفية عملها لحماية تطبيقك من هجمات XSS وCode Injection
|
| 129 |
+
</p>
|
| 130 |
+
<div class="card-tags">
|
| 131 |
+
<span class="tag">مبتدئ</span>
|
| 132 |
+
<span class="tag">أساسي</span>
|
| 133 |
+
</div>
|
| 134 |
+
<button class="card-btn" onclick="showSection('fundamentals')">تعلم المزيد</button>
|
| 135 |
+
</div>
|
| 136 |
+
|
| 137 |
+
<!-- CSP Level 3 -->
|
| 138 |
+
<div class="guide-card">
|
| 139 |
+
<div class="card-icon">
|
| 140 |
+
<img src="imgs/csp_code_7.jpg" alt="CSP Level 3" class="icon-image">
|
| 141 |
+
</div>
|
| 142 |
+
<h3 class="card-title">CSP Level 3</h3>
|
| 143 |
+
<p class="card-description">
|
| 144 |
+
استكشاف أحدث ميزات CSP Level 3 بما في ذلك Trusted Types وScript Sources المحسنة
|
| 145 |
+
</p>
|
| 146 |
+
<div class="card-tags">
|
| 147 |
+
<span class="tag tag-advanced">متقدم</span>
|
| 148 |
+
<span class="tag tag-new">جديد 2025</span>
|
| 149 |
+
</div>
|
| 150 |
+
<button class="card-btn" onclick="showSection('csp3')">استكشف الآن</button>
|
| 151 |
+
</div>
|
| 152 |
+
|
| 153 |
+
<!-- Trusted Types -->
|
| 154 |
+
<div class="guide-card">
|
| 155 |
+
<div class="card-icon">
|
| 156 |
+
<img src="imgs/trusted_types_7.jpg" alt="Trusted Types" class="icon-image">
|
| 157 |
+
</div>
|
| 158 |
+
<h3 class="card-title">Trusted Types API</h3>
|
| 159 |
+
<p class="card-description">
|
| 160 |
+
حماية متقدمة من DOM XSS باستخدام Trusted Types API في المتصفحات الحديثة
|
| 161 |
+
</p>
|
| 162 |
+
<div class="card-tags">
|
| 163 |
+
<span class="tag tag-advanced">متقدم</span>
|
| 164 |
+
<span class="tag tag-new">جديد 2025</span>
|
| 165 |
+
</div>
|
| 166 |
+
<button class="card-btn" onclick="showSection('trusted-types')">تعلم الآن</button>
|
| 167 |
+
</div>
|
| 168 |
+
|
| 169 |
+
<!-- Implementation -->
|
| 170 |
+
<div class="guide-card">
|
| 171 |
+
<div class="card-icon">
|
| 172 |
+
<img src="imgs/web_security_8.png" alt="تنفيذ CSP" class="icon-image">
|
| 173 |
+
</div>
|
| 174 |
+
<h3 class="card-title">التنفيذ العملي</h3>
|
| 175 |
+
<p class="card-description">
|
| 176 |
+
خطوات عملية لتطبيق CSP في مشاريعك مع أمثلة كود حقيقية وأدوات الاختبار
|
| 177 |
+
</p>
|
| 178 |
+
<div class="card-tags">
|
| 179 |
+
<span class="tag">عملي</span>
|
| 180 |
+
<span class="tag">تطبيقي</span>
|
| 181 |
+
</div>
|
| 182 |
+
<button class="card-btn" onclick="showSection('implementation')">ابدأ التنفيذ</button>
|
| 183 |
+
</div>
|
| 184 |
+
</div>
|
| 185 |
+
</div>
|
| 186 |
+
</section>
|
| 187 |
+
|
| 188 |
+
<!-- Code Examples Section -->
|
| 189 |
+
<section id="examples" class="examples">
|
| 190 |
+
<div class="container">
|
| 191 |
+
<div class="section-header">
|
| 192 |
+
<h2 class="section-title">أمثلة عملية قابلة للتجربة</h2>
|
| 193 |
+
<p class="section-description">
|
| 194 |
+
جرب أمثلة حقيقية لسياسة أمان المحتوى واختبر تأثيرها على أمان التطبيق
|
| 195 |
+
</p>
|
| 196 |
+
</div>
|
| 197 |
+
|
| 198 |
+
<div class="examples-tabs">
|
| 199 |
+
<button class="tab-btn active" onclick="showExampleTab('basic')">CSP الأساسي</button>
|
| 200 |
+
<button class="tab-btn" onclick="showExampleTab('advanced')">CSP المتقدم</button>
|
| 201 |
+
<button class="tab-btn" onclick="showExampleTab('trusted-types')">Trusted Types</button>
|
| 202 |
+
<button class="tab-btn" onclick="showExampleTab('headers')">الأمان المتقدم</button>
|
| 203 |
+
</div>
|
| 204 |
+
|
| 205 |
+
<!-- Basic CSP Example -->
|
| 206 |
+
<div id="basic-example" class="example-content active">
|
| 207 |
+
<div class="code-example">
|
| 208 |
+
<div class="example-header">
|
| 209 |
+
<h3>مثال CSP أساسي - حماية من XSS</h3>
|
| 210 |
+
<div class="example-actions">
|
| 211 |
+
<button class="btn-icon" onclick="copyCode('basic-csp')">
|
| 212 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 213 |
+
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
|
| 214 |
+
</svg>
|
| 215 |
+
</button>
|
| 216 |
+
</div>
|
| 217 |
+
</div>
|
| 218 |
+
|
| 219 |
+
<div class="code-container">
|
| 220 |
+
<pre><code id="basic-csp" class="language-http">// إعداد CSP أساسي في Header
|
| 221 |
+
Content-Security-Policy:
|
| 222 |
+
default-src 'self';
|
| 223 |
+
script-src 'self' 'unsafe-inline';
|
| 224 |
+
style-src 'self' 'unsafe-inline';
|
| 225 |
+
img-src 'self' data: https:;
|
| 226 |
+
font-src 'self' https://fonts.gstatic.com;
|
| 227 |
+
connect-src 'self' https://api.example.com;
|
| 228 |
+
frame-ancestors 'none';
|
| 229 |
+
base-uri 'self';
|
| 230 |
+
form-action 'self';
|
| 231 |
+
|
| 232 |
+
// أو عبر Meta Tag
|
| 233 |
+
<meta http-equiv="Content-Security-Policy" content="
|
| 234 |
+
default-src 'self';
|
| 235 |
+
script-src 'self' 'unsafe-inline';
|
| 236 |
+
style-src 'self' 'unsafe-inline';
|
| 237 |
+
img-src 'self' data: https:;
|
| 238 |
+
"></code></pre>
|
| 239 |
+
</div>
|
| 240 |
+
|
| 241 |
+
<div class="example-demo">
|
| 242 |
+
<h4>🛡️ نتائج الحماية:</h4>
|
| 243 |
+
<ul>
|
| 244 |
+
<li>✅ منع تحميل السكريبت من مصادر خارجية</li>
|
| 245 |
+
<li>✅ حماية من معظم هجمات XSS</li>
|
| 246 |
+
<li>✅ التحكم في مصادر الصور والموارد</li>
|
| 247 |
+
<li>⚠️ يتطلب مراجعة للمصادر المسموحة</li>
|
| 248 |
+
</ul>
|
| 249 |
+
</div>
|
| 250 |
+
</div>
|
| 251 |
+
</div>
|
| 252 |
+
|
| 253 |
+
<!-- Advanced CSP Example -->
|
| 254 |
+
<div id="advanced-example" class="example-content">
|
| 255 |
+
<div class="code-example">
|
| 256 |
+
<div class="example-header">
|
| 257 |
+
<h3>CSP متقدم - حماية شاملة 2025</h3>
|
| 258 |
+
<div class="example-actions">
|
| 259 |
+
<button class="btn-icon" onclick="copyCode('advanced-csp')">
|
| 260 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 261 |
+
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
|
| 262 |
+
</svg>
|
| 263 |
+
</button>
|
| 264 |
+
</div>
|
| 265 |
+
</div>
|
| 266 |
+
|
| 267 |
+
<div class="code-container">
|
| 268 |
+
<pre><code id="advanced-csp" class="language-http">// CSP متقدم مع ميزات 2025
|
| 269 |
+
Content-Security-Policy:
|
| 270 |
+
// المصادر الأساسية
|
| 271 |
+
default-src 'self';
|
| 272 |
+
base-uri 'self';
|
| 273 |
+
frame-ancestors 'none';
|
| 274 |
+
|
| 275 |
+
// السكريبت - حماية متقدمة
|
| 276 |
+
script-src 'self'
|
| 277 |
+
'nonce-{random-nonce}'
|
| 278 |
+
'strict-dynamic'
|
| 279 |
+
https://cdn.jsdelivr.net
|
| 280 |
+
https://unpkg.com;
|
| 281 |
+
|
| 282 |
+
// الأنماط - CSS آمن
|
| 283 |
+
style-src 'self'
|
| 284 |
+
'unsafe-inline'
|
| 285 |
+
https://fonts.googleapis.com
|
| 286 |
+
https://cdn.jsdelivr.net;
|
| 287 |
+
|
| 288 |
+
// الصور والوسائط
|
| 289 |
+
img-src 'self'
|
| 290 |
+
data:
|
| 291 |
+
https:
|
| 292 |
+
blob:;
|
| 293 |
+
media-src 'self' https:;
|
| 294 |
+
font-src 'self'
|
| 295 |
+
https://fonts.gstatic.com
|
| 296 |
+
https://cdn.jsdelivr.net;
|
| 297 |
+
|
| 298 |
+
// الشبكات والاتصالات
|
| 299 |
+
connect-src 'self'
|
| 300 |
+
wss:
|
| 301 |
+
https://api.example.com
|
| 302 |
+
https://*.analytics.com;
|
| 303 |
+
|
| 304 |
+
// الأطر والإطارات الفرعية
|
| 305 |
+
frame-src 'none';
|
| 306 |
+
object-src 'none';
|
| 307 |
+
worker-src 'self' blob:;
|
| 308 |
+
|
| 309 |
+
// ميزات المتصفح
|
| 310 |
+
form-action 'self';
|
| 311 |
+
upgrade-insecure-requests;
|
| 312 |
+
block-all-mixed-content;
|
| 313 |
+
report-uri /csp-report;
|
| 314 |
+
|
| 315 |
+
// منع التحميل التلقائي
|
| 316 |
+
autoplay-src 'none';
|
| 317 |
+
camera-src 'none';
|
| 318 |
+
microphone-src 'none';
|
| 319 |
+
geolocation-src 'none';</code></pre>
|
| 320 |
+
</div>
|
| 321 |
+
|
| 322 |
+
<div class="example-demo">
|
| 323 |
+
<h4>🚀 ميزات الحماية المتقدمة:</h4>
|
| 324 |
+
<ul>
|
| 325 |
+
<li>✅ Nonce-based script protection</li>
|
| 326 |
+
<li>✅ Strict Dynamic للسكريبت الآمن</li>
|
| 327 |
+
<li>✅ حماية من Mixed Content</li>
|
| 328 |
+
<li>✅ منع الوصول للكاميرا والميكروفون</li>
|
| 329 |
+
<li>✅ WebSocket Secure connections</li>
|
| 330 |
+
<li>✅ Worker isolation</li>
|
| 331 |
+
</ul>
|
| 332 |
+
</div>
|
| 333 |
+
</div>
|
| 334 |
+
</div>
|
| 335 |
+
|
| 336 |
+
<!-- Trusted Types Example -->
|
| 337 |
+
<div id="trusted-types-example" class="example-content">
|
| 338 |
+
<div class="code-example">
|
| 339 |
+
<div class="example-header">
|
| 340 |
+
<h3>Trusted Types API - حماية DOM من XSS</h3>
|
| 341 |
+
<div class="example-actions">
|
| 342 |
+
<button class="btn-icon" onclick="copyCode('trusted-types-code')">
|
| 343 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 344 |
+
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
|
| 345 |
+
</svg>
|
| 346 |
+
</button>
|
| 347 |
+
</div>
|
| 348 |
+
</div>
|
| 349 |
+
|
| 350 |
+
<div class="code-container">
|
| 351 |
+
<pre><code id="trusted-types-code" class="language-javascript">// تفعيل Trusted Types
|
| 352 |
+
if (window.trustedTypes) {
|
| 353 |
+
// إنشاء Policy للـ HTML
|
| 354 |
+
const htmlPolicy = trustedTypes.createPolicy('myPolicy', {
|
| 355 |
+
createHTML: (input) => {
|
| 356 |
+
// تنظيف وتحقق من HTML
|
| 357 |
+
return DOMPurify.sanitize(input, {
|
| 358 |
+
ALLOWED_TAGS: ['b', 'i', 'em', 'strong'],
|
| 359 |
+
ALLOWED_ATTR: []
|
| 360 |
+
});
|
| 361 |
+
}
|
| 362 |
+
});
|
| 363 |
+
|
| 364 |
+
// إنشاء Policy للـ URLs
|
| 365 |
+
const urlPolicy = trustedTypes.createPolicy('urlPolicy', {
|
| 366 |
+
createURL: (input) => {
|
| 367 |
+
const url = new URL(input);
|
| 368 |
+
if (url.protocol === 'javascript:') {
|
| 369 |
+
throw new Error('Blocked dangerous protocol');
|
| 370 |
+
}
|
| 371 |
+
return url;
|
| 372 |
+
}
|
| 373 |
+
});
|
| 374 |
+
|
| 375 |
+
// إنشاء Policy للـ Scripts
|
| 376 |
+
const scriptPolicy = trustedTypes.createPolicy('scriptPolicy', {
|
| 377 |
+
createScript: (input) => {
|
| 378 |
+
if (input.includes('<script>')) {
|
| 379 |
+
throw new Error('Script tags not allowed');
|
| 380 |
+
}
|
| 381 |
+
return input;
|
| 382 |
+
}
|
| 383 |
+
});
|
| 384 |
+
}
|
| 385 |
+
|
| 386 |
+
// استخدام آمن للـ Trusted Types
|
| 387 |
+
function safeElementCreation() {
|
| 388 |
+
// استخدام Trusted HTML
|
| 389 |
+
const safeHTML = htmlPolicy.createHTML(
|
| 390 |
+
'<b>نص آمن</b> <i>بخط مائل</i>'
|
| 391 |
+
);
|
| 392 |
+
element.innerHTML = safeHTML;
|
| 393 |
+
|
| 394 |
+
// استخدام Trusted URL
|
| 395 |
+
const safeURL = urlPolicy.createURL('https://example.com');
|
| 396 |
+
link.href = safeURL;
|
| 397 |
+
|
| 398 |
+
// استخدام Trusted Script
|
| 399 |
+
const safeScript = scriptPolicy.createScript(
|
| 400 |
+
'console.log("Hello from trusted script");'
|
| 401 |
+
);
|
| 402 |
+
// script.textContent = safeScript;
|
| 403 |
+
}</code></pre>
|
| 404 |
+
</div>
|
| 405 |
+
|
| 406 |
+
<div class="example-demo">
|
| 407 |
+
<h4>🔒 فوائد Trusted Types:</h4>
|
| 408 |
+
<ul>
|
| 409 |
+
<li>✅ حماية كاملة من DOM XSS</li>
|
| 410 |
+
<li>✅ التحقق من صحة HTML قبل الإدراج</li>
|
| 411 |
+
<li>✅ منع javascript: URLs الخطيرة</li>
|
| 412 |
+
<li>✅ عزل الـ JavaScript غير الموثوق</li>
|
| 413 |
+
<li>✅ متوافق مع CSP</li>
|
| 414 |
+
</ul>
|
| 415 |
+
</div>
|
| 416 |
+
</div>
|
| 417 |
+
</div>
|
| 418 |
+
|
| 419 |
+
<!-- Advanced Headers Example -->
|
| 420 |
+
<div id="headers-example" class="example-content">
|
| 421 |
+
<div class="code-example">
|
| 422 |
+
<div class="example-header">
|
| 423 |
+
<h3>رؤوس الأمان المتقدمة - طبقة حماية شاملة</h3>
|
| 424 |
+
<div class="example-actions">
|
| 425 |
+
<button class="btn-icon" onclick="copyCode('headers-code')">
|
| 426 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 427 |
+
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
|
| 428 |
+
</svg>
|
| 429 |
+
</button>
|
| 430 |
+
</div>
|
| 431 |
+
</div>
|
| 432 |
+
|
| 433 |
+
<div class="code-container">
|
| 434 |
+
<pre><code id="headers-code" class="language-http">// مجموعة شاملة من رؤوس الأمان 2025
|
| 435 |
+
// Content Security Policy
|
| 436 |
+
Content-Security-Policy:
|
| 437 |
+
default-src 'self';
|
| 438 |
+
script-src 'self' 'nonce-{random}' 'strict-dynamic';
|
| 439 |
+
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
|
| 440 |
+
img-src 'self' data: https:;
|
| 441 |
+
font-src 'self' https://fonts.gstatic.com;
|
| 442 |
+
connect-src 'self' wss: https:;
|
| 443 |
+
frame-ancestors 'none';
|
| 444 |
+
base-uri 'self';
|
| 445 |
+
form-action 'self';
|
| 446 |
+
upgrade-insecure-requests;
|
| 447 |
+
block-all-mixed-content;
|
| 448 |
+
|
| 449 |
+
// Cross-Origin Policies
|
| 450 |
+
Cross-Origin-Embedder-Policy: require-corp
|
| 451 |
+
Cross-Origin-Opener-Policy: same-origin
|
| 452 |
+
Cross-Origin-Resource-Policy: same-origin
|
| 453 |
+
|
| 454 |
+
// Feature Policies (دعم محدود، استخدم بدلاً منه Permissions Policy)
|
| 455 |
+
Feature-Policy:
|
| 456 |
+
geolocation 'none';
|
| 457 |
+
microphone 'none';
|
| 458 |
+
camera 'none';
|
| 459 |
+
fullscreen 'self';
|
| 460 |
+
autoplay 'none';
|
| 461 |
+
|
| 462 |
+
// Permissions Policy (البديل الحديث)
|
| 463 |
+
Permissions-Policy:
|
| 464 |
+
geolocation=(),
|
| 465 |
+
microphone=(),
|
| 466 |
+
camera=(),
|
| 467 |
+
payment=(),
|
| 468 |
+
usb=(),
|
| 469 |
+
accelerometer=(),
|
| 470 |
+
gyroscope=(),
|
| 471 |
+
magnetometer=(),
|
| 472 |
+
fullscreen=(self);
|
| 473 |
+
|
| 474 |
+
// HTTP Strict Transport Security
|
| 475 |
+
Strict-Transport-Security:
|
| 476 |
+
max-age=31536000;
|
| 477 |
+
includeSubDomains;
|
| 478 |
+
preload;
|
| 479 |
+
|
| 480 |
+
// XSS Protection
|
| 481 |
+
X-XSS-Protection: 1; mode=block
|
| 482 |
+
|
| 483 |
+
// Content Type Sniffing Protection
|
| 484 |
+
X-Content-Type-Options: nosniff
|
| 485 |
+
|
| 486 |
+
// Frame Protection
|
| 487 |
+
X-Frame-Options: DENY
|
| 488 |
+
|
| 489 |
+
// Referrer Policy
|
| 490 |
+
Referrer-Policy: strict-origin-when-cross-origin
|
| 491 |
+
|
| 492 |
+
// Cache Control for Sensitive Pages
|
| 493 |
+
Cache-Control: no-cache, no-store, must-revalidate
|
| 494 |
+
Pragma: no-cache
|
| 495 |
+
|
| 496 |
+
// Hide Server Information
|
| 497 |
+
Server: (remove or obfuscate)
|
| 498 |
+
X-Powered-By: (remove)
|
| 499 |
+
|
| 500 |
+
// CORS Configuration
|
| 501 |
+
Access-Control-Allow-Origin: https://yourdomain.com
|
| 502 |
+
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
|
| 503 |
+
Access-Control-Allow-Headers: Content-Type, Authorization
|
| 504 |
+
Access-Control-Allow-Credentials: true
|
| 505 |
+
|
| 506 |
+
// Trusted Types (في JavaScript)
|
| 507 |
+
Content-Security-Policy: require-trusted-types-for 'script'</code></pre>
|
| 508 |
+
</div>
|
| 509 |
+
|
| 510 |
+
<div class="example-demo">
|
| 511 |
+
<h4>🛡️ حماية شاملة مع:</h4>
|
| 512 |
+
<ul>
|
| 513 |
+
<li>✅ Cross-Origin Isolation</li>
|
| 514 |
+
<li>✅ Feature Permissions Control</li>
|
| 515 |
+
<li>✅ HTTPS Enforcement</li>
|
| 516 |
+
<li>✅ XSS Prevention</li>
|
| 517 |
+
<li>✅ Clickjacking Protection</li>
|
| 518 |
+
<li>✅ MIME Type Validation</li>
|
| 519 |
+
<li>✅ Trusted Types Enforcement</li>
|
| 520 |
+
</ul>
|
| 521 |
+
</div>
|
| 522 |
+
</div>
|
| 523 |
+
</div>
|
| 524 |
+
</div>
|
| 525 |
+
</section>
|
| 526 |
+
|
| 527 |
+
<!-- Tools Section -->
|
| 528 |
+
<section id="tools" class="tools">
|
| 529 |
+
<div class="container">
|
| 530 |
+
<div class="section-header">
|
| 531 |
+
<h2 class="section-title">الأدوات التفاعلية</h2>
|
| 532 |
+
<p class="section-description">
|
| 533 |
+
أدوات عملية لاختبار وتطبيق سياسة أمان المحتوى في مشاريعك
|
| 534 |
+
</p>
|
| 535 |
+
</div>
|
| 536 |
+
|
| 537 |
+
<div class="tools-grid">
|
| 538 |
+
<!-- CSP Builder -->
|
| 539 |
+
<div class="tool-card">
|
| 540 |
+
<div class="tool-header">
|
| 541 |
+
<img src="imgs/csp_code_3.png" alt="CSP Builder" class="tool-icon">
|
| 542 |
+
<h3>CSP Builder</h3>
|
| 543 |
+
</div>
|
| 544 |
+
<p class="tool-description">
|
| 545 |
+
منشئ تفاعلي لبناء سياسة أمان المحتوى المناسبة لمشروعك
|
| 546 |
+
</p>
|
| 547 |
+
<div class="tool-features">
|
| 548 |
+
<span class="feature">✓ واجهة بصرية</span>
|
| 549 |
+
<span class="feature">✓ اختبارات فورية</span>
|
| 550 |
+
<span class="feature">✓ تصدير الكود</span>
|
| 551 |
+
</div>
|
| 552 |
+
<button class="btn btn-primary" onclick="openCSPBuilder()">استخدام الأداة</button>
|
| 553 |
+
</div>
|
| 554 |
+
|
| 555 |
+
<!-- CSP Tester -->
|
| 556 |
+
<div class="tool-card">
|
| 557 |
+
<div class="tool-header">
|
| 558 |
+
<img src="imgs/browser_security_6.png" alt="CSP Tester" class="tool-icon">
|
| 559 |
+
<h3>CSP Tester</h3>
|
| 560 |
+
</div>
|
| 561 |
+
<p class="tool-description">
|
| 562 |
+
اختبار سياسة أمان المحتوى وتحديد نقاط الضعف والثغرات
|
| 563 |
+
</p>
|
| 564 |
+
<div class="tool-features">
|
| 565 |
+
<span class="feature">✓ تحليل السياسات</span>
|
| 566 |
+
<span class="feature">✓ تقارير مفصلة</span>
|
| 567 |
+
<span class="feature">✓ توصيات للتحسين</span>
|
| 568 |
+
</div>
|
| 569 |
+
<button class="btn btn-primary" onclick="openCSPTester()">اختبار السياسة</button>
|
| 570 |
+
</div>
|
| 571 |
+
|
| 572 |
+
<!-- Security Scanner -->
|
| 573 |
+
<div class="tool-card">
|
| 574 |
+
<div class="tool-header">
|
| 575 |
+
<img src="imgs/cyber_threats_0.png" alt="Security Scanner" class="tool-icon">
|
| 576 |
+
<h3>Security Scanner</h3>
|
| 577 |
+
</div>
|
| 578 |
+
<p class="tool-description">
|
| 579 |
+
فحص شامل لأمان التطبيق وتحديد التهديدات المحتملة
|
| 580 |
+
</p>
|
| 581 |
+
<div class="tool-features">
|
| 582 |
+
<span class="feature">✓ فحص XSS</span>
|
| 583 |
+
<span class="feature">✓ تحليل Headers</span>
|
| 584 |
+
<span class="feature">✓ تقييم المخاطر</span>
|
| 585 |
+
</div>
|
| 586 |
+
<button class="btn btn-primary" onclick="openSecurityScanner()">بدء الفحص</button>
|
| 587 |
+
</div>
|
| 588 |
+
|
| 589 |
+
<!-- Code Analyzer -->
|
| 590 |
+
<div class="tool-card">
|
| 591 |
+
<div class="tool-header">
|
| 592 |
+
<img src="imgs/xss_prevention_3.png" alt="Code Analyzer" class="tool-icon">
|
| 593 |
+
<h3>Code Analyzer</h3>
|
| 594 |
+
</div>
|
| 595 |
+
<p class="tool-description">
|
| 596 |
+
تحليل كود JavaScript وتطبيق أفضل الممارسات الأمنية
|
| 597 |
+
</p>
|
| 598 |
+
<div class="tool-features">
|
| 599 |
+
<span class="feature">✓ تحليل الكود</span>
|
| 600 |
+
<span class="feature">✓ اقتراحات التحسين</span>
|
| 601 |
+
<span class="feature">✓ Trusted Types</span>
|
| 602 |
+
</div>
|
| 603 |
+
<button class="btn btn-primary" onclick="openCodeAnalyzer()">تحليل الكود</button>
|
| 604 |
+
</div>
|
| 605 |
+
</div>
|
| 606 |
+
</div>
|
| 607 |
+
</section>
|
| 608 |
+
|
| 609 |
+
<!-- Modern Technologies Section -->
|
| 610 |
+
<section id="technologies" class="technologies">
|
| 611 |
+
<div class="container">
|
| 612 |
+
<div class="section-header">
|
| 613 |
+
<h2 class="section-title">التقنيات الحديثة 2025</h2>
|
| 614 |
+
<p class="section-description">
|
| 615 |
+
استكشاف أحدث تقنيات أمان الويب والممارسات المتقدمة في حماية التطبيقات
|
| 616 |
+
</p>
|
| 617 |
+
</div>
|
| 618 |
+
|
| 619 |
+
<div class="technologies-grid">
|
| 620 |
+
<!-- CSP Level 3 -->
|
| 621 |
+
<div class="tech-card">
|
| 622 |
+
<div class="tech-badge">CSP 3.0</div>
|
| 623 |
+
<img src="imgs/web_security_4.jpg" alt="CSP Level 3" class="tech-image">
|
| 624 |
+
<h3>CSP Level 3</h3>
|
| 625 |
+
<p>أحدث إصدار من سياسة أمان المحتوى مع ميزات محسنة مثل strict-dynamic وtrusted-types</p>
|
| 626 |
+
<ul class="tech-features">
|
| 627 |
+
<li>Strict Dynamic Policy</li>
|
| 628 |
+
<li>Trusted Types Integration</li>
|
| 629 |
+
<li>Script Hash Improvements</li>
|
| 630 |
+
<li>Dynamic Source Validation</li>
|
| 631 |
+
</ul>
|
| 632 |
+
</div>
|
| 633 |
+
|
| 634 |
+
<!-- Trusted Types -->
|
| 635 |
+
<div class="tech-card">
|
| 636 |
+
<div class="tech-badge">Modern API</div>
|
| 637 |
+
<img src="imgs/trusted_types_0.png" alt="Trusted Types" class="tech-image">
|
| 638 |
+
<h3>Trusted Types API</h3>
|
| 639 |
+
<p>حماية متقدمة من DOM XSS من خلال التحقق من صحة البيانات قبل إدراجها في DOM</p>
|
| 640 |
+
<ul class="tech-features">
|
| 641 |
+
<li>HTML Sanitization</li>
|
| 642 |
+
<li>URL Validation</li>
|
| 643 |
+
<li>Script Isolation</li>
|
| 644 |
+
<li>Policy-based Protection</li>
|
| 645 |
+
</ul>
|
| 646 |
+
</div>
|
| 647 |
+
|
| 648 |
+
<!-- Cross-Origin Isolation -->
|
| 649 |
+
<div class="tech-card">
|
| 650 |
+
<div class="tech-badge">Security</div>
|
| 651 |
+
<img src="imgs/data_protection_5.jpg" alt="Cross-Origin Isolation" class="tech-image">
|
| 652 |
+
<h3>Cross-Origin Isolation</h3>
|
| 653 |
+
<p>عزل المصادر المتقاطعة لحماية من هجمات Spectre وتحسين أمان الذاكرة</p>
|
| 654 |
+
<ul class="tech-features">
|
| 655 |
+
<li>COEP/COOP Headers</li>
|
| 656 |
+
<li>CORP Resource Policy</li>
|
| 657 |
+
<li>SharedArrayBuffer Support</li>
|
| 658 |
+
<li>Performance Isolation</li>
|
| 659 |
+
</ul>
|
| 660 |
+
</div>
|
| 661 |
+
|
| 662 |
+
<!-- WebAssembly Security -->
|
| 663 |
+
<div class="tech-card">
|
| 664 |
+
<div class="tech-badge">Performance</div>
|
| 665 |
+
<img src="imgs/ssl_security_5.png" alt="WebAssembly Security" class="tech-image">
|
| 666 |
+
<h3>WebAssembly Security</h3>
|
| 667 |
+
<p>أمان متقدم لتطبيقات WebAssembly مع sandbox isolation وتحقق من التوقيع الرقمي</p>
|
| 668 |
+
<ul class="tech-features">
|
| 669 |
+
<li>Sandbox Execution</li>
|
| 670 |
+
<li>Digital Signature Verification</li>
|
| 671 |
+
<li>Memory Safety</li>
|
| 672 |
+
<li>Capability-based Security</li>
|
| 673 |
+
</ul>
|
| 674 |
+
</div>
|
| 675 |
+
|
| 676 |
+
<!-- Subresource Integrity -->
|
| 677 |
+
<div class="tech-card">
|
| 678 |
+
<div class="tech-badge">Integrity</div>
|
| 679 |
+
<img src="imgs/data_protection_1.jpeg" alt="SRI" class="tech-image">
|
| 680 |
+
<h3>Subresource Integrity</h3>
|
| 681 |
+
<p>ضمان سلامة الموارد الخارجية من خلال التحقق من hashes التشفيرية</p>
|
| 682 |
+
<ul class="tech-features">
|
| 683 |
+
<li>Crypto Hash Validation</li>
|
| 684 |
+
<li>External Resource Protection</li>
|
| 685 |
+
<li>CDN Security</li>
|
| 686 |
+
<li>Integrity Attribute</li>
|
| 687 |
+
</ul>
|
| 688 |
+
</div>
|
| 689 |
+
|
| 690 |
+
<!-- Permissions Policy -->
|
| 691 |
+
<div class="tech-card">
|
| 692 |
+
<div class="tech-badge">Access Control</div>
|
| 693 |
+
<img src="imgs/browser_security_8.png" alt="Permissions Policy" class="tech-image">
|
| 694 |
+
<h3>Permissions Policy</h3>
|
| 695 |
+
<p>تحكم دقيق في صلاحيات الوصول للميزات الحساسة مثل الكاميرا والميكروفون</p>
|
| 696 |
+
<ul class="tech-features">
|
| 697 |
+
<li>Feature Granular Control</li>
|
| 698 |
+
<li>Permission Management</li>
|
| 699 |
+
<li>User Consent Integration</li>
|
| 700 |
+
<li>Cross-origin Permissions</li>
|
| 701 |
+
</ul>
|
| 702 |
+
</div>
|
| 703 |
+
</div>
|
| 704 |
+
</div>
|
| 705 |
+
</section>
|
| 706 |
+
|
| 707 |
+
<!-- Footer -->
|
| 708 |
+
<footer class="footer">
|
| 709 |
+
<div class="container">
|
| 710 |
+
<div class="footer-content">
|
| 711 |
+
<div class="footer-section">
|
| 712 |
+
<h4>مشروع سياسة أمان المحتوى</h4>
|
| 713 |
+
<p>دليل شامل لأحدث تقنيات حماية تطبيقات الويب من التهديدات السيبرانية</p>
|
| 714 |
+
<div class="footer-social">
|
| 715 |
+
<a href="#" class="social-link">
|
| 716 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 717 |
+
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z"/>
|
| 718 |
+
</svg>
|
| 719 |
+
</a>
|
| 720 |
+
<a href="#" class="social-link">
|
| 721 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 722 |
+
<path d="M16 8a6 6 0 016 6v7h-4v-7a2 2 0 00-2-2 2 2 0 00-2 2v7h-4v-7a6 6 0 016-6zM2 9h4v12H2z"/>
|
| 723 |
+
<circle cx="4" cy="4" r="2"/>
|
| 724 |
+
</svg>
|
| 725 |
+
</a>
|
| 726 |
+
<a href="#" class="social-link">
|
| 727 |
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
| 728 |
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
|
| 729 |
+
</svg>
|
| 730 |
+
</a>
|
| 731 |
+
</div>
|
| 732 |
+
</div>
|
| 733 |
+
|
| 734 |
+
<div class="footer-section">
|
| 735 |
+
<h4>روابط مفيدة</h4>
|
| 736 |
+
<ul class="footer-links">
|
| 737 |
+
<li><a href="#guide">الدليل الشامل</a></li>
|
| 738 |
+
<li><a href="#examples">أمثلة عملية</a></li>
|
| 739 |
+
<li><a href="#tools">الأدوات التفاعلية</a></li>
|
| 740 |
+
<li><a href="#technologies">التقنيات الحديثة</a></li>
|
| 741 |
+
</ul>
|
| 742 |
+
</div>
|
| 743 |
+
|
| 744 |
+
<div class="footer-section">
|
| 745 |
+
<h4>المصادر</h4>
|
| 746 |
+
<ul class="footer-links">
|
| 747 |
+
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" target="_blank">MDN CSP Documentation</a></li>
|
| 748 |
+
<li><a href="https://w3c.github.io/webappsec-csp/" target="_blank">W3C CSP Specification</a></li>
|
| 749 |
+
<li><a href="https://web.dev/trusted-types/" target="_blank">Trusted Types Guide</a></li>
|
| 750 |
+
<li><a href="https://owasp.org/www-project-secure-headers/" target="_blank">OWASP Secure Headers</a></li>
|
| 751 |
+
</ul>
|
| 752 |
+
</div>
|
| 753 |
+
|
| 754 |
+
<div class="footer-section">
|
| 755 |
+
<h4>تواصل معنا</h4>
|
| 756 |
+
<p>لديك استفسار أو اقتراح؟ تواصل معنا لمساعدتك في تطبيق أفضل المما��سات الأمنية</p>
|
| 757 |
+
<a href="mailto:contact@content-security-policy.com" class="footer-email">contact@content-security-policy.com</a>
|
| 758 |
+
</div>
|
| 759 |
+
</div>
|
| 760 |
+
|
| 761 |
+
<div class="footer-bottom">
|
| 762 |
+
<p>© 2025 مشروع سياسة أمان المحتوى. جميع الحقوق محفوظة.</p>
|
| 763 |
+
<p>تم التطوير بأحدث التقنيات لضمان أقصى درجات الأمان</p>
|
| 764 |
+
</div>
|
| 765 |
+
</div>
|
| 766 |
+
</footer>
|
| 767 |
+
|
| 768 |
+
<!-- CSP Builder Modal -->
|
| 769 |
+
<div id="cspBuilderModal" class="modal">
|
| 770 |
+
<div class="modal-content">
|
| 771 |
+
<div class="modal-header">
|
| 772 |
+
<h3>CSP Builder - منشئ سياسة أمان المحتوى</h3>
|
| 773 |
+
<button class="modal-close" onclick="closeModal('cspBuilderModal')">×</button>
|
| 774 |
+
</div>
|
| 775 |
+
<div class="modal-body">
|
| 776 |
+
<div class="builder-tabs">
|
| 777 |
+
<button class="tab-btn active" onclick="showBuilderTab('basic')">إعدادات أساسية</button>
|
| 778 |
+
<button class="tab-btn" onclick="showBuilderTab('advanced')">إعدادات متقدمة</button>
|
| 779 |
+
<button class="tab-btn" onclick="showBuilderTab('testing')">اختبار السياسة</button>
|
| 780 |
+
</div>
|
| 781 |
+
|
| 782 |
+
<div id="basic-builder" class="builder-tab active">
|
| 783 |
+
<div class="builder-section">
|
| 784 |
+
<h4>المصادر المسموحة</h4>
|
| 785 |
+
<div class="form-group">
|
| 786 |
+
<label>JavaScript Sources:</label>
|
| 787 |
+
<input type="text" id="jsSources" placeholder="'self' 'unsafe-inline' https://cdn.example.com">
|
| 788 |
+
</div>
|
| 789 |
+
<div class="form-group">
|
| 790 |
+
<label>CSS Sources:</label>
|
| 791 |
+
<input type="text" id="cssSources" placeholder="'self' 'unsafe-inline' https://fonts.googleapis.com">
|
| 792 |
+
</div>
|
| 793 |
+
<div class="form-group">
|
| 794 |
+
<label>Image Sources:</label>
|
| 795 |
+
<input type="text" id="imgSources" placeholder="'self' data: https:">
|
| 796 |
+
</div>
|
| 797 |
+
<div class="form-group">
|
| 798 |
+
<label>Font Sources:</label>
|
| 799 |
+
<input type="text" id="fontSources" placeholder="'self' https://fonts.gstatic.com">
|
| 800 |
+
</div>
|
| 801 |
+
<div class="form-group">
|
| 802 |
+
<label>Connect Sources:</label>
|
| 803 |
+
<input type="text" id="connectSources" placeholder="'self' wss: https://api.example.com">
|
| 804 |
+
</div>
|
| 805 |
+
</div>
|
| 806 |
+
|
| 807 |
+
<div class="builder-section">
|
| 808 |
+
<h4>إعدادات الحماية</h4>
|
| 809 |
+
<div class="checkbox-group">
|
| 810 |
+
<label><input type="checkbox" id="blockMixedContent"> Block Mixed Content</label>
|
| 811 |
+
<label><input type="checkbox" id="upgradeInsecure"> Upgrade Insecure Requests</label>
|
| 812 |
+
<label><input type="checkbox" id="frameAncestors"> Allow Frame Embedding</label>
|
| 813 |
+
<label><input type="checkbox" id="strictDynamic"> Enable Strict Dynamic</label>
|
| 814 |
+
</div>
|
| 815 |
+
</div>
|
| 816 |
+
|
| 817 |
+
<div class="generated-csp">
|
| 818 |
+
<h4>سياسة الأمان المُولدة:</h4>
|
| 819 |
+
<pre><code id="generatedCSP">default-src 'self';</code></pre>
|
| 820 |
+
<button class="btn btn-primary" onclick="copyGeneratedCSP()">نسخ السياسة</button>
|
| 821 |
+
</div>
|
| 822 |
+
</div>
|
| 823 |
+
|
| 824 |
+
<div id="advanced-builder" class="builder-tab">
|
| 825 |
+
<div class="builder-section">
|
| 826 |
+
<h4>الإعدادات المتقدمة</h4>
|
| 827 |
+
<div class="form-group">
|
| 828 |
+
<label>Nonce للسكريبت:</label>
|
| 829 |
+
<input type="text" id="scriptNonce" placeholder="اختياري - سيتم توليده تلقائياً">
|
| 830 |
+
</div>
|
| 831 |
+
<div class="form-group">
|
| 832 |
+
<label>Hashes للسكريبت:</label>
|
| 833 |
+
<textarea id="scriptHashes" placeholder="sha256-..., sha384-..., sha512-..."></textarea>
|
| 834 |
+
</div>
|
| 835 |
+
<div class="form-group">
|
| 836 |
+
<label>Worker Sources:</label>
|
| 837 |
+
<input type="text" id="workerSources" placeholder="'self' blob:">
|
| 838 |
+
</div>
|
| 839 |
+
<div class="form-group">
|
| 840 |
+
<label>Media Sources:</label>
|
| 841 |
+
<input type="text" id="mediaSources" placeholder="'self' https:">
|
| 842 |
+
</div>
|
| 843 |
+
</div>
|
| 844 |
+
</div>
|
| 845 |
+
|
| 846 |
+
<div id="testing-builder" class="builder-tab">
|
| 847 |
+
<div class="builder-section">
|
| 848 |
+
<h4>اختبار السياسة</h4>
|
| 849 |
+
<div class="test-results">
|
| 850 |
+
<div class="test-item">
|
| 851 |
+
<span class="test-status success">✓</span>
|
| 852 |
+
<span>Default-src Policy</span>
|
| 853 |
+
</div>
|
| 854 |
+
<div class="test-item">
|
| 855 |
+
<span class="test-status success">✓</span>
|
| 856 |
+
<span>Script-src Validation</span>
|
| 857 |
+
</div>
|
| 858 |
+
<div class="test-item">
|
| 859 |
+
<span class="test-status warning">⚠</span>
|
| 860 |
+
<span>Unsafe-inline Warning</span>
|
| 861 |
+
</div>
|
| 862 |
+
<div class="test-item">
|
| 863 |
+
<span class="test-status error">✗</span>
|
| 864 |
+
<span>External Scripts Blocked</span>
|
| 865 |
+
</div>
|
| 866 |
+
</div>
|
| 867 |
+
</div>
|
| 868 |
+
</div>
|
| 869 |
+
</div>
|
| 870 |
+
</div>
|
| 871 |
+
</div>
|
| 872 |
+
|
| 873 |
+
<!-- Scripts -->
|
| 874 |
+
<script src="js/main.js"></script>
|
| 875 |
+
<script src="js/components.js"></script>
|
| 876 |
+
<script src="js/tools.js"></script>
|
| 877 |
+
</body>
|
| 878 |
+
</html>
|
js/3d-interactive-interface.js
ADDED
|
@@ -0,0 +1,1089 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* 3D Interactive Security Interface
|
| 3 |
+
* Modern 3D visualization and interaction system for security analysis
|
| 4 |
+
* Author: MiniMax Agent
|
| 5 |
+
* Date: 2025-12-10
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
class Security3DInterface {
|
| 9 |
+
constructor(containerId) {
|
| 10 |
+
this.containerId = containerId;
|
| 11 |
+
this.scene = null;
|
| 12 |
+
this.camera = null;
|
| 13 |
+
this.renderer = null;
|
| 14 |
+
this.controls = null;
|
| 15 |
+
this.securityObjects = new Map();
|
| 16 |
+
this.animationId = null;
|
| 17 |
+
this.isInitialized = false;
|
| 18 |
+
this.userInteractions = [];
|
| 19 |
+
this.securityVisualization = new SecurityVisualization();
|
| 20 |
+
this.gestureRecognizer = new GestureRecognizer();
|
| 21 |
+
this.touchHandler = new TouchHandler();
|
| 22 |
+
this.vrSupported = false;
|
| 23 |
+
this.arSupported = false;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
async initialize() {
|
| 27 |
+
try {
|
| 28 |
+
console.log('🎮 Initializing 3D Security Interface...');
|
| 29 |
+
|
| 30 |
+
// Check for WebGL support
|
| 31 |
+
if (!this.checkWebGLSupport()) {
|
| 32 |
+
throw new Error('WebGL not supported');
|
| 33 |
+
}
|
| 34 |
+
|
| 35 |
+
// Initialize Three.js components
|
| 36 |
+
await this.initializeThreeJS();
|
| 37 |
+
|
| 38 |
+
// Setup 3D security visualization
|
| 39 |
+
await this.setupSecurityVisualization();
|
| 40 |
+
|
| 41 |
+
// Initialize interaction systems
|
| 42 |
+
this.initializeInteractionSystems();
|
| 43 |
+
|
| 44 |
+
// Setup gesture recognition
|
| 45 |
+
await this.initializeGestureRecognition();
|
| 46 |
+
|
| 47 |
+
// Check for VR/AR support
|
| 48 |
+
this.checkXRSupport();
|
| 49 |
+
|
| 50 |
+
// Start animation loop
|
| 51 |
+
this.startAnimation();
|
| 52 |
+
|
| 53 |
+
this.isInitialized = true;
|
| 54 |
+
console.log('✅ 3D Security Interface initialized successfully');
|
| 55 |
+
|
| 56 |
+
} catch (error) {
|
| 57 |
+
console.error('❌ Failed to initialize 3D Interface:', error);
|
| 58 |
+
this.fallbackTo2D();
|
| 59 |
+
}
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
checkWebGLSupport() {
|
| 63 |
+
try {
|
| 64 |
+
const canvas = document.createElement('canvas');
|
| 65 |
+
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
| 66 |
+
return !!gl;
|
| 67 |
+
} catch (e) {
|
| 68 |
+
return false;
|
| 69 |
+
}
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
async initializeThreeJS() {
|
| 73 |
+
// Import Three.js dynamically
|
| 74 |
+
if (typeof THREE === 'undefined') {
|
| 75 |
+
await this.loadThreeJS();
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
// Create scene
|
| 79 |
+
this.scene = new THREE.Scene();
|
| 80 |
+
this.scene.background = new THREE.Color(0x0a0a0a);
|
| 81 |
+
this.scene.fog = new THREE.Fog(0x0a0a0a, 10, 50);
|
| 82 |
+
|
| 83 |
+
// Create camera
|
| 84 |
+
this.camera = new THREE.PerspectiveCamera(
|
| 85 |
+
75,
|
| 86 |
+
window.innerWidth / window.innerHeight,
|
| 87 |
+
0.1,
|
| 88 |
+
1000
|
| 89 |
+
);
|
| 90 |
+
this.camera.position.set(0, 5, 10);
|
| 91 |
+
|
| 92 |
+
// Create renderer
|
| 93 |
+
this.renderer = new THREE.WebGLRenderer({
|
| 94 |
+
antialias: true,
|
| 95 |
+
alpha: true,
|
| 96 |
+
powerPreference: "high-performance"
|
| 97 |
+
});
|
| 98 |
+
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
| 99 |
+
this.renderer.setPixelRatio(window.devicePixelRatio);
|
| 100 |
+
this.renderer.shadowMap.enabled = true;
|
| 101 |
+
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
| 102 |
+
|
| 103 |
+
// Add renderer to container
|
| 104 |
+
const container = document.getElementById(this.containerId);
|
| 105 |
+
if (!container) {
|
| 106 |
+
throw new Error(`Container with id ${this.containerId} not found`);
|
| 107 |
+
}
|
| 108 |
+
container.appendChild(this.renderer.domElement);
|
| 109 |
+
|
| 110 |
+
// Initialize controls
|
| 111 |
+
this.initializeControls();
|
| 112 |
+
|
| 113 |
+
// Setup lighting
|
| 114 |
+
this.setupLighting();
|
| 115 |
+
|
| 116 |
+
// Handle window resize
|
| 117 |
+
window.addEventListener('resize', () => this.handleResize());
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
async loadThreeJS() {
|
| 121 |
+
return new Promise((resolve, reject) => {
|
| 122 |
+
const script = document.createElement('script');
|
| 123 |
+
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js';
|
| 124 |
+
script.onload = resolve;
|
| 125 |
+
script.onerror = reject;
|
| 126 |
+
document.head.appendChild(script);
|
| 127 |
+
});
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
initializeControls() {
|
| 131 |
+
// Simple orbit controls implementation
|
| 132 |
+
this.controls = {
|
| 133 |
+
target: new THREE.Vector3(0, 0, 0),
|
| 134 |
+
spherical: new THREE.Spherical(),
|
| 135 |
+
rotateSpeed: 0.1,
|
| 136 |
+
zoomSpeed: 1.2,
|
| 137 |
+
panSpeed: 0.8,
|
| 138 |
+
|
| 139 |
+
update: () => {
|
| 140 |
+
this.camera.lookAt(this.controls.target);
|
| 141 |
+
},
|
| 142 |
+
|
| 143 |
+
rotate: (deltaX, deltaY) => {
|
| 144 |
+
this.spherical.theta -= deltaX * this.controls.rotateSpeed;
|
| 145 |
+
this.spherical.phi += deltaY * this.controls.rotateSpeed;
|
| 146 |
+
this.spherical.phi = Math.max(0.1, Math.min(Math.PI - 0.1, this.spherical.phi));
|
| 147 |
+
|
| 148 |
+
const pos = new THREE.Vector3().setFromSpherical(this.spherical);
|
| 149 |
+
this.camera.position.copy(pos);
|
| 150 |
+
},
|
| 151 |
+
|
| 152 |
+
zoom: (delta) => {
|
| 153 |
+
const distance = this.camera.position.distanceTo(this.controls.target);
|
| 154 |
+
const newDistance = distance * (1 + delta * this.controls.zoomSpeed);
|
| 155 |
+
this.camera.position.setLength(newDistance);
|
| 156 |
+
},
|
| 157 |
+
|
| 158 |
+
pan: (deltaX, deltaY) => {
|
| 159 |
+
const moveVector = new THREE.Vector3();
|
| 160 |
+
const cameraDistance = this.camera.position.distanceTo(this.controls.target);
|
| 161 |
+
|
| 162 |
+
// Calculate movement in camera space
|
| 163 |
+
moveVector.set(-deltaX * cameraDistance * 0.001, deltaY * cameraDistance * 0.001, 0);
|
| 164 |
+
moveVector.applyQuaternion(this.camera.quaternion);
|
| 165 |
+
|
| 166 |
+
this.controls.target.add(moveVector);
|
| 167 |
+
}
|
| 168 |
+
};
|
| 169 |
+
|
| 170 |
+
this.controls.spherical.setFromVector3(this.camera.position.clone().sub(this.controls.target));
|
| 171 |
+
|
| 172 |
+
// Mouse event handlers
|
| 173 |
+
this.setupMouseControls();
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
setupMouseControls() {
|
| 177 |
+
const canvas = this.renderer.domElement;
|
| 178 |
+
let isMouseDown = false;
|
| 179 |
+
let mouseStart = { x: 0, y: 0 };
|
| 180 |
+
let lastMouse = { x: 0, y: 0 };
|
| 181 |
+
|
| 182 |
+
canvas.addEventListener('mousedown', (e) => {
|
| 183 |
+
isMouseDown = true;
|
| 184 |
+
mouseStart = { x: e.clientX, y: e.clientY };
|
| 185 |
+
lastMouse = { x: e.clientX, y: e.clientY };
|
| 186 |
+
canvas.style.cursor = 'grabbing';
|
| 187 |
+
});
|
| 188 |
+
|
| 189 |
+
canvas.addEventListener('mousemove', (e) => {
|
| 190 |
+
if (!isMouseDown) return;
|
| 191 |
+
|
| 192 |
+
const deltaX = e.clientX - lastMouse.x;
|
| 193 |
+
const deltaY = e.clientY - lastMouse.y;
|
| 194 |
+
|
| 195 |
+
if (e.buttons === 1) { // Left click - rotate
|
| 196 |
+
this.controls.rotate(deltaX, deltaY);
|
| 197 |
+
} else if (e.buttons === 2) { // Right click - pan
|
| 198 |
+
this.controls.pan(deltaX, deltaY);
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
lastMouse = { x: e.clientX, y: e.clientY };
|
| 202 |
+
});
|
| 203 |
+
|
| 204 |
+
canvas.addEventListener('mouseup', () => {
|
| 205 |
+
isMouseDown = false;
|
| 206 |
+
canvas.style.cursor = 'grab';
|
| 207 |
+
});
|
| 208 |
+
|
| 209 |
+
canvas.addEventListener('wheel', (e) => {
|
| 210 |
+
e.preventDefault();
|
| 211 |
+
this.controls.zoom(e.deltaY > 0 ? 1 : -1);
|
| 212 |
+
});
|
| 213 |
+
|
| 214 |
+
// Prevent context menu
|
| 215 |
+
canvas.addEventListener('contextmenu', (e) => e.preventDefault());
|
| 216 |
+
|
| 217 |
+
canvas.style.cursor = 'grab';
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
setupLighting() {
|
| 221 |
+
// Ambient light
|
| 222 |
+
const ambientLight = new THREE.AmbientLight(0x404040, 0.3);
|
| 223 |
+
this.scene.add(ambientLight);
|
| 224 |
+
|
| 225 |
+
// Main directional light
|
| 226 |
+
const directionalLight = new THREE.DirectionalLight(0x00e0d5, 1);
|
| 227 |
+
directionalLight.position.set(10, 10, 5);
|
| 228 |
+
directionalLight.castShadow = true;
|
| 229 |
+
directionalLight.shadow.mapSize.width = 2048;
|
| 230 |
+
directionalLight.shadow.mapSize.height = 2048;
|
| 231 |
+
this.scene.add(directionalLight);
|
| 232 |
+
|
| 233 |
+
// Point lights for accent
|
| 234 |
+
const pointLight1 = new THREE.PointLight(0x00e0d5, 0.5, 10);
|
| 235 |
+
pointLight1.position.set(-5, 5, 5);
|
| 236 |
+
this.scene.add(pointLight1);
|
| 237 |
+
|
| 238 |
+
const pointLight2 = new THREE.PointLight(0xff6b6b, 0.3, 8);
|
| 239 |
+
pointLight2.position.set(5, -3, -5);
|
| 240 |
+
this.scene.add(pointLight2);
|
| 241 |
+
|
| 242 |
+
// Rim light
|
| 243 |
+
const rimLight = new THREE.DirectionalLight(0xffffff, 0.3);
|
| 244 |
+
rimLight.position.set(-10, -10, -5);
|
| 245 |
+
this.scene.add(rimLight);
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
async setupSecurityVisualization() {
|
| 249 |
+
// Create security dashboard in 3D space
|
| 250 |
+
this.createSecurityDashboard();
|
| 251 |
+
|
| 252 |
+
// Create threat visualization
|
| 253 |
+
this.createThreatVisualization();
|
| 254 |
+
|
| 255 |
+
// Create network visualization
|
| 256 |
+
this.createNetworkVisualization();
|
| 257 |
+
|
| 258 |
+
// Create performance metrics visualization
|
| 259 |
+
this.createPerformanceVisualization();
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
createSecurityDashboard() {
|
| 263 |
+
// Main dashboard panel
|
| 264 |
+
const dashboardGeometry = new THREE.PlaneGeometry(8, 4);
|
| 265 |
+
const dashboardMaterial = new THREE.MeshPhongMaterial({
|
| 266 |
+
color: 0x1a1a1a,
|
| 267 |
+
transparent: true,
|
| 268 |
+
opacity: 0.9,
|
| 269 |
+
side: THREE.DoubleSide
|
| 270 |
+
});
|
| 271 |
+
const dashboard = new THREE.Mesh(dashboardGeometry, dashboardMaterial);
|
| 272 |
+
dashboard.position.set(0, 0, -5);
|
| 273 |
+
dashboard.castShadow = true;
|
| 274 |
+
dashboard.receiveShadow = true;
|
| 275 |
+
this.scene.add(dashboard);
|
| 276 |
+
|
| 277 |
+
// Dashboard frame
|
| 278 |
+
const frameGeometry = new THREE.RingGeometry(4.2, 4.3, 32);
|
| 279 |
+
const frameMaterial = new THREE.MeshBasicMaterial({
|
| 280 |
+
color: 0x00e0d5,
|
| 281 |
+
transparent: true,
|
| 282 |
+
opacity: 0.6
|
| 283 |
+
});
|
| 284 |
+
const frame = new THREE.Mesh(frameGeometry, frameMaterial);
|
| 285 |
+
frame.position.copy(dashboard.position);
|
| 286 |
+
this.scene.add(frame);
|
| 287 |
+
|
| 288 |
+
// Store dashboard reference
|
| 289 |
+
this.securityObjects.set('dashboard', dashboard);
|
| 290 |
+
|
| 291 |
+
// Add animated border
|
| 292 |
+
this.createAnimatedBorder(frame);
|
| 293 |
+
}
|
| 294 |
+
|
| 295 |
+
createThreatVisualization() {
|
| 296 |
+
// Create threat indicators as floating spheres
|
| 297 |
+
const threatTypes = [
|
| 298 |
+
{ type: 'XSS', color: 0xff6b6b, position: { x: -2, y: 1, z: -3 } },
|
| 299 |
+
{ type: 'SQL Injection', color: 0xffa500, position: { x: 0, y: 1, z: -3 } },
|
| 300 |
+
{ type: 'CSRF', color: 0xffff00, position: { x: 2, y: 1, z: -3 } },
|
| 301 |
+
{ type: 'Clickjacking', color: 0x9d4edd, position: { x: -1, y: -1, z: -3 } },
|
| 302 |
+
{ type: 'RCE', color: 0xff0000, position: { x: 1, y: -1, z: -3 } }
|
| 303 |
+
];
|
| 304 |
+
|
| 305 |
+
threatTypes.forEach(threat => {
|
| 306 |
+
const sphere = this.createThreatSphere(threat);
|
| 307 |
+
this.scene.add(sphere);
|
| 308 |
+
this.securityObjects.set(`threat_${threat.type}`, sphere);
|
| 309 |
+
});
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
createThreatSphere(threat) {
|
| 313 |
+
// Create sphere geometry
|
| 314 |
+
const geometry = new THREE.SphereGeometry(0.3, 16, 16);
|
| 315 |
+
|
| 316 |
+
// Create animated material
|
| 317 |
+
const material = new THREE.MeshPhongMaterial({
|
| 318 |
+
color: threat.color,
|
| 319 |
+
transparent: true,
|
| 320 |
+
opacity: 0.8,
|
| 321 |
+
emissive: threat.color,
|
| 322 |
+
emissiveIntensity: 0.2
|
| 323 |
+
});
|
| 324 |
+
|
| 325 |
+
const sphere = new THREE.Mesh(geometry, material);
|
| 326 |
+
sphere.position.set(threat.position.x, threat.position.y, threat.position.z);
|
| 327 |
+
sphere.castShadow = true;
|
| 328 |
+
|
| 329 |
+
// Add pulsing animation
|
| 330 |
+
sphere.userData = {
|
| 331 |
+
type: 'threat_indicator',
|
| 332 |
+
threatType: threat.type,
|
| 333 |
+
baseScale: 1,
|
| 334 |
+
pulseSpeed: 2 + Math.random() * 2,
|
| 335 |
+
originalColor: threat.color
|
| 336 |
+
};
|
| 337 |
+
|
| 338 |
+
return sphere;
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
createNetworkVisualization() {
|
| 342 |
+
// Create network nodes
|
| 343 |
+
const nodes = [];
|
| 344 |
+
const connections = [];
|
| 345 |
+
|
| 346 |
+
// Generate network topology
|
| 347 |
+
const nodeCount = 12;
|
| 348 |
+
for (let i = 0; i < nodeCount; i++) {
|
| 349 |
+
const angle = (i / nodeCount) * Math.PI * 2;
|
| 350 |
+
const radius = 3;
|
| 351 |
+
const x = Math.cos(angle) * radius;
|
| 352 |
+
const z = Math.sin(angle) * radius;
|
| 353 |
+
const y = Math.sin(angle * 3) * 1; // Add some height variation
|
| 354 |
+
|
| 355 |
+
const node = this.createNetworkNode(new THREE.Vector3(x, y, z), i);
|
| 356 |
+
nodes.push(node);
|
| 357 |
+
this.scene.add(node);
|
| 358 |
+
|
| 359 |
+
// Create connections to nearby nodes
|
| 360 |
+
for (let j = i + 1; j < Math.min(i + 4, nodeCount); j++) {
|
| 361 |
+
const targetAngle = (j / nodeCount) * Math.PI * 2;
|
| 362 |
+
const targetX = Math.cos(targetAngle) * radius;
|
| 363 |
+
const targetZ = Math.sin(targetAngle) * radius;
|
| 364 |
+
const targetY = Math.sin(targetAngle * 3) * 1;
|
| 365 |
+
|
| 366 |
+
const connection = this.createNetworkConnection(
|
| 367 |
+
node.position,
|
| 368 |
+
new THREE.Vector3(targetX, targetY, targetZ)
|
| 369 |
+
);
|
| 370 |
+
connections.push(connection);
|
| 371 |
+
this.scene.add(connection);
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
this.securityObjects.set('network_nodes', nodes);
|
| 376 |
+
this.securityObjects.set('network_connections', connections);
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
createNetworkNode(position, index) {
|
| 380 |
+
const geometry = new THREE.OctahedronGeometry(0.1, 0);
|
| 381 |
+
const material = new THREE.MeshPhongMaterial({
|
| 382 |
+
color: 0x00e0d5,
|
| 383 |
+
transparent: true,
|
| 384 |
+
opacity: 0.7,
|
| 385 |
+
emissive: 0x00e0d5,
|
| 386 |
+
emissiveIntensity: 0.3
|
| 387 |
+
});
|
| 388 |
+
|
| 389 |
+
const node = new THREE.Mesh(geometry, material);
|
| 390 |
+
node.position.copy(position);
|
| 391 |
+
node.castShadow = true;
|
| 392 |
+
|
| 393 |
+
// Add particle effect
|
| 394 |
+
const particles = this.createParticleEffect(position, 0x00e0d5);
|
| 395 |
+
this.scene.add(particles);
|
| 396 |
+
|
| 397 |
+
node.userData = {
|
| 398 |
+
type: 'network_node',
|
| 399 |
+
nodeId: index,
|
| 400 |
+
connections: 0
|
| 401 |
+
};
|
| 402 |
+
|
| 403 |
+
return node;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
createNetworkConnection(start, end) {
|
| 407 |
+
const geometry = new THREE.BufferGeometry();
|
| 408 |
+
const positions = new Float32Array([
|
| 409 |
+
start.x, start.y, start.z,
|
| 410 |
+
end.x, end.y, end.z
|
| 411 |
+
]);
|
| 412 |
+
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
| 413 |
+
|
| 414 |
+
const material = new THREE.LineBasicMaterial({
|
| 415 |
+
color: 0x00e0d5,
|
| 416 |
+
transparent: true,
|
| 417 |
+
opacity: 0.4
|
| 418 |
+
});
|
| 419 |
+
|
| 420 |
+
const line = new THREE.Line(geometry, material);
|
| 421 |
+
line.userData = {
|
| 422 |
+
type: 'network_connection',
|
| 423 |
+
start: start,
|
| 424 |
+
end: end,
|
| 425 |
+
active: true
|
| 426 |
+
};
|
| 427 |
+
|
| 428 |
+
return line;
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
createPerformanceVisualization() {
|
| 432 |
+
// Create performance charts as 3D bars
|
| 433 |
+
const metrics = [
|
| 434 |
+
{ name: 'CPU Usage', value: 45, color: 0x00e0d5 },
|
| 435 |
+
{ name: 'Memory', value: 68, color: 0x9d4edd },
|
| 436 |
+
{ name: 'Network', value: 32, color: 0xff6b6b },
|
| 437 |
+
{ name: 'Disk I/O', value: 23, color: 0xffa500 }
|
| 438 |
+
];
|
| 439 |
+
|
| 440 |
+
metrics.forEach((metric, index) => {
|
| 441 |
+
const bar = this.createPerformanceBar(metric, index);
|
| 442 |
+
this.scene.add(bar);
|
| 443 |
+
this.securityObjects.set(`perf_${metric.name}`, bar);
|
| 444 |
+
});
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
createPerformanceBar(metric, index) {
|
| 448 |
+
const height = (metric.value / 100) * 3; // Scale to 3 units max
|
| 449 |
+
const geometry = new THREE.BoxGeometry(0.3, height, 0.3);
|
| 450 |
+
|
| 451 |
+
const material = new THREE.MeshPhongMaterial({
|
| 452 |
+
color: metric.color,
|
| 453 |
+
transparent: true,
|
| 454 |
+
opacity: 0.8,
|
| 455 |
+
emissive: metric.color,
|
| 456 |
+
emissiveIntensity: 0.2
|
| 457 |
+
});
|
| 458 |
+
|
| 459 |
+
const bar = new THREE.Mesh(geometry, material);
|
| 460 |
+
bar.position.set(-3 + index * 2, height / 2 - 2, 2);
|
| 461 |
+
bar.castShadow = true;
|
| 462 |
+
|
| 463 |
+
bar.userData = {
|
| 464 |
+
type: 'performance_bar',
|
| 465 |
+
metric: metric.name,
|
| 466 |
+
value: metric.value,
|
| 467 |
+
originalHeight: height
|
| 468 |
+
};
|
| 469 |
+
|
| 470 |
+
return bar;
|
| 471 |
+
}
|
| 472 |
+
|
| 473 |
+
createParticleEffect(position, color) {
|
| 474 |
+
const particleCount = 20;
|
| 475 |
+
const geometry = new THREE.BufferGeometry();
|
| 476 |
+
const positions = new Float32Array(particleCount * 3);
|
| 477 |
+
const colors = new Float32Array(particleCount * 3);
|
| 478 |
+
|
| 479 |
+
for (let i = 0; i < particleCount; i++) {
|
| 480 |
+
positions[i * 3] = position.x + (Math.random() - 0.5) * 2;
|
| 481 |
+
positions[i * 3 + 1] = position.y + (Math.random() - 0.5) * 2;
|
| 482 |
+
positions[i * 3 + 2] = position.z + (Math.random() - 0.5) * 2;
|
| 483 |
+
|
| 484 |
+
colors[i * 3] = (color >> 16 & 255) / 255;
|
| 485 |
+
colors[i * 3 + 1] = (color >> 8 & 255) / 255;
|
| 486 |
+
colors[i * 3 + 2] = (color & 255) / 255;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
| 490 |
+
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
| 491 |
+
|
| 492 |
+
const material = new THREE.PointsMaterial({
|
| 493 |
+
size: 0.05,
|
| 494 |
+
vertexColors: true,
|
| 495 |
+
transparent: true,
|
| 496 |
+
opacity: 0.6
|
| 497 |
+
});
|
| 498 |
+
|
| 499 |
+
const particles = new THREE.Points(geometry, material);
|
| 500 |
+
particles.userData = {
|
| 501 |
+
type: 'particle_effect',
|
| 502 |
+
positions: positions,
|
| 503 |
+
originalPositions: positions.slice(),
|
| 504 |
+
time: 0
|
| 505 |
+
};
|
| 506 |
+
|
| 507 |
+
return particles;
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
createAnimatedBorder(frame) {
|
| 511 |
+
// Create animated border effect
|
| 512 |
+
const borderPoints = [];
|
| 513 |
+
const segments = 64;
|
| 514 |
+
const radius = 4.25;
|
| 515 |
+
|
| 516 |
+
for (let i = 0; i <= segments; i++) {
|
| 517 |
+
const angle = (i / segments) * Math.PI * 2;
|
| 518 |
+
borderPoints.push(
|
| 519 |
+
Math.cos(angle) * radius,
|
| 520 |
+
Math.sin(angle) * radius,
|
| 521 |
+
0
|
| 522 |
+
);
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
const geometry = new THREE.BufferGeometry();
|
| 526 |
+
geometry.setAttribute('position', new THREE.Float32BufferAttribute(borderPoints, 3));
|
| 527 |
+
|
| 528 |
+
const material = new THREE.LineBasicMaterial({
|
| 529 |
+
color: 0x00e0d5,
|
| 530 |
+
transparent: true,
|
| 531 |
+
opacity: 0.8
|
| 532 |
+
});
|
| 533 |
+
|
| 534 |
+
const border = new THREE.Line(geometry, material);
|
| 535 |
+
frame.add(border);
|
| 536 |
+
|
| 537 |
+
frame.userData = {
|
| 538 |
+
type: 'animated_border',
|
| 539 |
+
time: 0,
|
| 540 |
+
segments: segments
|
| 541 |
+
};
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
initializeInteractionSystems() {
|
| 545 |
+
// Setup raycaster for object picking
|
| 546 |
+
this.raycaster = new THREE.Raycaster();
|
| 547 |
+
this.mouse = new THREE.Vector2();
|
| 548 |
+
|
| 549 |
+
// Setup click handlers
|
| 550 |
+
this.renderer.domElement.addEventListener('click', (e) => this.handleClick(e));
|
| 551 |
+
|
| 552 |
+
// Setup hover handlers
|
| 553 |
+
this.renderer.domElement.addEventListener('mousemove', (e) => this.handleHover(e));
|
| 554 |
+
|
| 555 |
+
// Initialize touch handlers
|
| 556 |
+
this.touchHandler.initialize(this.renderer.domElement);
|
| 557 |
+
}
|
| 558 |
+
|
| 559 |
+
async initializeGestureRecognition() {
|
| 560 |
+
try {
|
| 561 |
+
// Setup gesture recognition for touch devices
|
| 562 |
+
await this.gestureRecognizer.initialize();
|
| 563 |
+
this.gestureRecognizer.onGesture((gesture) => this.handleGesture(gesture));
|
| 564 |
+
} catch (error) {
|
| 565 |
+
console.warn('Gesture recognition not available:', error);
|
| 566 |
+
}
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
checkXRSupport() {
|
| 570 |
+
// Check for VR support
|
| 571 |
+
if (navigator.xr) {
|
| 572 |
+
navigator.xr.isSessionSupported('immersive-vr').then((supported) => {
|
| 573 |
+
this.vrSupported = supported;
|
| 574 |
+
if (supported) {
|
| 575 |
+
console.log('🥽 VR support detected');
|
| 576 |
+
}
|
| 577 |
+
});
|
| 578 |
+
}
|
| 579 |
+
|
| 580 |
+
// Check for AR support
|
| 581 |
+
if (navigator.xr) {
|
| 582 |
+
navigator.xr.isSessionSupported('immersive-ar').then((supported) => {
|
| 583 |
+
this.arSupported = supported;
|
| 584 |
+
if (supported) {
|
| 585 |
+
console.log('📱 AR support detected');
|
| 586 |
+
}
|
| 587 |
+
});
|
| 588 |
+
}
|
| 589 |
+
}
|
| 590 |
+
|
| 591 |
+
handleClick(event) {
|
| 592 |
+
// Calculate mouse position in normalized device coordinates
|
| 593 |
+
const rect = this.renderer.domElement.getBoundingClientRect();
|
| 594 |
+
this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
| 595 |
+
this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
| 596 |
+
|
| 597 |
+
// Update raycaster
|
| 598 |
+
this.raycaster.setFromCamera(this.mouse, this.camera);
|
| 599 |
+
|
| 600 |
+
// Get intersections
|
| 601 |
+
const intersects = this.raycaster.intersectObjects(this.scene.children);
|
| 602 |
+
|
| 603 |
+
if (intersects.length > 0) {
|
| 604 |
+
const intersected = intersects[0].object;
|
| 605 |
+
this.onObjectClick(intersected, intersects[0]);
|
| 606 |
+
}
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
handleHover(event) {
|
| 610 |
+
// Calculate mouse position
|
| 611 |
+
const rect = this.renderer.domElement.getBoundingClientRect();
|
| 612 |
+
this.mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
| 613 |
+
this.mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
| 614 |
+
|
| 615 |
+
// Update raycaster
|
| 616 |
+
this.raycaster.setFromCamera(this.mouse, this.camera);
|
| 617 |
+
|
| 618 |
+
// Get intersections
|
| 619 |
+
const intersects = this.raycaster.intersectObjects(this.scene.children);
|
| 620 |
+
|
| 621 |
+
// Reset all object materials
|
| 622 |
+
this.scene.children.forEach(obj => {
|
| 623 |
+
if (obj.material && obj.material.emissive) {
|
| 624 |
+
obj.material.emissive.setHex(obj.userData.originalColor || 0x000000);
|
| 625 |
+
}
|
| 626 |
+
});
|
| 627 |
+
|
| 628 |
+
// Highlight hovered object
|
| 629 |
+
if (intersects.length > 0) {
|
| 630 |
+
const intersected = intersects[0].object;
|
| 631 |
+
if (intersected.material && intersected.material.emissive) {
|
| 632 |
+
intersected.material.emissive.setHex(0xffffff);
|
| 633 |
+
intersected.material.emissiveIntensity = 0.5;
|
| 634 |
+
}
|
| 635 |
+
}
|
| 636 |
+
}
|
| 637 |
+
|
| 638 |
+
onObjectClick(object, intersection) {
|
| 639 |
+
const userData = object.userData;
|
| 640 |
+
|
| 641 |
+
switch (userData.type) {
|
| 642 |
+
case 'threat_indicator':
|
| 643 |
+
this.showThreatDetails(userData.threatType);
|
| 644 |
+
break;
|
| 645 |
+
|
| 646 |
+
case 'network_node':
|
| 647 |
+
this.highlightNetworkConnections(userData.nodeId);
|
| 648 |
+
break;
|
| 649 |
+
|
| 650 |
+
case 'performance_bar':
|
| 651 |
+
this.showPerformanceDetails(userData.metric);
|
| 652 |
+
break;
|
| 653 |
+
|
| 654 |
+
case 'dashboard':
|
| 655 |
+
this.interactWithDashboard(intersection.point);
|
| 656 |
+
break;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
// Add click effect
|
| 660 |
+
this.createClickEffect(intersection.point);
|
| 661 |
+
|
| 662 |
+
// Log interaction
|
| 663 |
+
this.userInteractions.push({
|
| 664 |
+
type: 'click',
|
| 665 |
+
object: userData.type,
|
| 666 |
+
position: intersection.point.clone(),
|
| 667 |
+
timestamp: Date.now()
|
| 668 |
+
});
|
| 669 |
+
}
|
| 670 |
+
|
| 671 |
+
handleGesture(gesture) {
|
| 672 |
+
switch (gesture.type) {
|
| 673 |
+
case 'swipe_left':
|
| 674 |
+
this.rotateView(0.5, 0);
|
| 675 |
+
break;
|
| 676 |
+
case 'swipe_right':
|
| 677 |
+
this.rotateView(-0.5, 0);
|
| 678 |
+
break;
|
| 679 |
+
case 'swipe_up':
|
| 680 |
+
this.zoomView(1);
|
| 681 |
+
break;
|
| 682 |
+
case 'swipe_down':
|
| 683 |
+
this.zoomView(-1);
|
| 684 |
+
break;
|
| 685 |
+
case 'pinch':
|
| 686 |
+
this.zoomView(gesture.scale > 1 ? 1 : -1);
|
| 687 |
+
break;
|
| 688 |
+
}
|
| 689 |
+
}
|
| 690 |
+
|
| 691 |
+
showThreatDetails(threatType) {
|
| 692 |
+
// Create floating info panel
|
| 693 |
+
const infoPanel = this.createInfoPanel(threatType);
|
| 694 |
+
this.scene.add(infoPanel);
|
| 695 |
+
|
| 696 |
+
// Auto-remove after 5 seconds
|
| 697 |
+
setTimeout(() => {
|
| 698 |
+
this.scene.remove(infoPanel);
|
| 699 |
+
}, 5000);
|
| 700 |
+
}
|
| 701 |
+
|
| 702 |
+
createInfoPanel(threatType) {
|
| 703 |
+
const panelGeometry = new THREE.PlaneGeometry(2, 1);
|
| 704 |
+
const canvas = document.createElement('canvas');
|
| 705 |
+
canvas.width = 512;
|
| 706 |
+
canvas.height = 256;
|
| 707 |
+
const context = canvas.getContext('2d');
|
| 708 |
+
|
| 709 |
+
// Draw threat information
|
| 710 |
+
context.fillStyle = '#1a1a1a';
|
| 711 |
+
context.fillRect(0, 0, 512, 256);
|
| 712 |
+
context.strokeStyle = '#00e0d5';
|
| 713 |
+
context.lineWidth = 4;
|
| 714 |
+
context.strokeRect(0, 0, 512, 256);
|
| 715 |
+
|
| 716 |
+
context.fillStyle = '#ffffff';
|
| 717 |
+
context.font = 'bold 24px Arial';
|
| 718 |
+
context.fillText(`Threat: ${threatType}`, 20, 40);
|
| 719 |
+
context.font = '16px Arial';
|
| 720 |
+
context.fillText('Severity: High', 20, 80);
|
| 721 |
+
context.fillText('Status: Active Monitoring', 20, 110);
|
| 722 |
+
context.fillText('Recommendations Available', 20, 140);
|
| 723 |
+
|
| 724 |
+
const texture = new THREE.CanvasTexture(canvas);
|
| 725 |
+
const material = new THREE.MeshBasicMaterial({
|
| 726 |
+
map: texture,
|
| 727 |
+
transparent: true
|
| 728 |
+
});
|
| 729 |
+
|
| 730 |
+
const panel = new THREE.Mesh(panelGeometry, material);
|
| 731 |
+
panel.position.set(0, 0, -2);
|
| 732 |
+
|
| 733 |
+
return panel;
|
| 734 |
+
}
|
| 735 |
+
|
| 736 |
+
createClickEffect(position) {
|
| 737 |
+
// Create expanding ring effect
|
| 738 |
+
const ringGeometry = new THREE.RingGeometry(0, 0.5, 32);
|
| 739 |
+
const ringMaterial = new THREE.MeshBasicMaterial({
|
| 740 |
+
color: 0x00e0d5,
|
| 741 |
+
transparent: true,
|
| 742 |
+
opacity: 0.8,
|
| 743 |
+
side: THREE.DoubleSide
|
| 744 |
+
});
|
| 745 |
+
|
| 746 |
+
const ring = new THREE.Mesh(ringGeometry, ringMaterial);
|
| 747 |
+
ring.position.copy(position);
|
| 748 |
+
ring.userData = {
|
| 749 |
+
type: 'click_effect',
|
| 750 |
+
startTime: Date.now(),
|
| 751 |
+
duration: 1000
|
| 752 |
+
};
|
| 753 |
+
|
| 754 |
+
this.scene.add(ring);
|
| 755 |
+
|
| 756 |
+
// Remove effect after animation
|
| 757 |
+
setTimeout(() => {
|
| 758 |
+
this.scene.remove(ring);
|
| 759 |
+
}, 1000);
|
| 760 |
+
}
|
| 761 |
+
|
| 762 |
+
rotateView(deltaX, deltaY) {
|
| 763 |
+
this.controls.rotate(deltaX * 50, deltaY * 50);
|
| 764 |
+
}
|
| 765 |
+
|
| 766 |
+
zoomView(delta) {
|
| 767 |
+
this.controls.zoom(delta);
|
| 768 |
+
}
|
| 769 |
+
|
| 770 |
+
startAnimation() {
|
| 771 |
+
const animate = () => {
|
| 772 |
+
this.animationId = requestAnimationFrame(animate);
|
| 773 |
+
|
| 774 |
+
// Update controls
|
| 775 |
+
this.controls.update();
|
| 776 |
+
|
| 777 |
+
// Animate objects
|
| 778 |
+
this.animateSecurityObjects();
|
| 779 |
+
|
| 780 |
+
// Update particle effects
|
| 781 |
+
this.updateParticleEffects();
|
| 782 |
+
|
| 783 |
+
// Update click effects
|
| 784 |
+
this.updateClickEffects();
|
| 785 |
+
|
| 786 |
+
// Render scene
|
| 787 |
+
this.renderer.render(this.scene, this.camera);
|
| 788 |
+
};
|
| 789 |
+
|
| 790 |
+
animate();
|
| 791 |
+
}
|
| 792 |
+
|
| 793 |
+
animateSecurityObjects() {
|
| 794 |
+
const time = Date.now() * 0.001;
|
| 795 |
+
|
| 796 |
+
this.scene.children.forEach(object => {
|
| 797 |
+
const userData = object.userData;
|
| 798 |
+
|
| 799 |
+
if (!userData) return;
|
| 800 |
+
|
| 801 |
+
switch (userData.type) {
|
| 802 |
+
case 'threat_indicator':
|
| 803 |
+
// Pulse animation
|
| 804 |
+
const pulseScale = 1 + Math.sin(time * userData.pulseSpeed) * 0.2;
|
| 805 |
+
object.scale.setScalar(userData.baseScale * pulseScale);
|
| 806 |
+
|
| 807 |
+
// Rotate slowly
|
| 808 |
+
object.rotation.y += 0.01;
|
| 809 |
+
break;
|
| 810 |
+
|
| 811 |
+
case 'performance_bar':
|
| 812 |
+
// Animate height based on value
|
| 813 |
+
const targetHeight = (userData.value / 100) * 3;
|
| 814 |
+
const currentHeight = object.geometry.parameters.height;
|
| 815 |
+
const newHeight = currentHeight + (targetHeight - currentHeight) * 0.1;
|
| 816 |
+
|
| 817 |
+
object.scale.y = newHeight / userData.originalHeight;
|
| 818 |
+
object.position.y = newHeight / 2 - 2;
|
| 819 |
+
break;
|
| 820 |
+
|
| 821 |
+
case 'animated_border':
|
| 822 |
+
// Rotate border
|
| 823 |
+
object.rotation.z = time * 0.5;
|
| 824 |
+
break;
|
| 825 |
+
}
|
| 826 |
+
});
|
| 827 |
+
}
|
| 828 |
+
|
| 829 |
+
updateParticleEffects() {
|
| 830 |
+
const time = Date.now() * 0.001;
|
| 831 |
+
|
| 832 |
+
this.scene.children.forEach(object => {
|
| 833 |
+
if (object.userData.type === 'particle_effect') {
|
| 834 |
+
const positions = object.geometry.attributes.position.array;
|
| 835 |
+
const originalPositions = object.userData.originalPositions;
|
| 836 |
+
|
| 837 |
+
for (let i = 0; i < positions.length; i += 3) {
|
| 838 |
+
positions[i] = originalPositions[i] + Math.sin(time + i) * 0.1;
|
| 839 |
+
positions[i + 1] = originalPositions[i + 1] + Math.cos(time + i) * 0.1;
|
| 840 |
+
positions[i + 2] = originalPositions[i + 2] + Math.sin(time * 2 + i) * 0.05;
|
| 841 |
+
}
|
| 842 |
+
|
| 843 |
+
object.geometry.attributes.position.needsUpdate = true;
|
| 844 |
+
}
|
| 845 |
+
});
|
| 846 |
+
}
|
| 847 |
+
|
| 848 |
+
updateClickEffects() {
|
| 849 |
+
const now = Date.now();
|
| 850 |
+
const effectsToRemove = [];
|
| 851 |
+
|
| 852 |
+
this.scene.children.forEach(object => {
|
| 853 |
+
if (object.userData.type === 'click_effect') {
|
| 854 |
+
const elapsed = now - object.userData.startTime;
|
| 855 |
+
const progress = elapsed / object.userData.duration;
|
| 856 |
+
|
| 857 |
+
if (progress >= 1) {
|
| 858 |
+
effectsToRemove.push(object);
|
| 859 |
+
} else {
|
| 860 |
+
const scale = progress * 3;
|
| 861 |
+
object.scale.setScalar(scale);
|
| 862 |
+
object.material.opacity = 0.8 * (1 - progress);
|
| 863 |
+
}
|
| 864 |
+
}
|
| 865 |
+
});
|
| 866 |
+
|
| 867 |
+
effectsToRemove.forEach(effect => {
|
| 868 |
+
this.scene.remove(effect);
|
| 869 |
+
});
|
| 870 |
+
}
|
| 871 |
+
|
| 872 |
+
handleResize() {
|
| 873 |
+
this.camera.aspect = window.innerWidth / window.innerHeight;
|
| 874 |
+
this.camera.updateProjectionMatrix();
|
| 875 |
+
this.renderer.setSize(window.innerWidth, window.innerHeight);
|
| 876 |
+
}
|
| 877 |
+
|
| 878 |
+
fallbackTo2D() {
|
| 879 |
+
console.log('⚠️ Falling back to 2D interface');
|
| 880 |
+
// Create simplified 2D version
|
| 881 |
+
const container = document.getElementById(this.containerId);
|
| 882 |
+
if (container) {
|
| 883 |
+
container.innerHTML = `
|
| 884 |
+
<div style="
|
| 885 |
+
width: 100%;
|
| 886 |
+
height: 100%;
|
| 887 |
+
background: linear-gradient(135deg, #1a1a1a, #2d2d2d);
|
| 888 |
+
display: flex;
|
| 889 |
+
align-items: center;
|
| 890 |
+
justify-content: center;
|
| 891 |
+
color: #00e0d5;
|
| 892 |
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 893 |
+
">
|
| 894 |
+
<div style="text-align: center;">
|
| 895 |
+
<h2>🔒 3D Security Interface</h2>
|
| 896 |
+
<p>Your browser doesn't support WebGL</p>
|
| 897 |
+
<p>Using enhanced 2D interface</p>
|
| 898 |
+
</div>
|
| 899 |
+
</div>
|
| 900 |
+
`;
|
| 901 |
+
}
|
| 902 |
+
}
|
| 903 |
+
|
| 904 |
+
// Public API methods
|
| 905 |
+
updateThreatStatus(threatType, status) {
|
| 906 |
+
const threatObject = this.securityObjects.get(`threat_${threatType}`);
|
| 907 |
+
if (threatObject) {
|
| 908 |
+
const intensity = status === 'active' ? 0.8 : 0.3;
|
| 909 |
+
threatObject.material.opacity = intensity;
|
| 910 |
+
threatObject.material.emissiveIntensity = intensity * 0.5;
|
| 911 |
+
}
|
| 912 |
+
}
|
| 913 |
+
|
| 914 |
+
updatePerformanceMetric(metricName, value) {
|
| 915 |
+
const perfObject = this.securityObjects.get(`perf_${metricName}`);
|
| 916 |
+
if (perfObject) {
|
| 917 |
+
perfObject.userData.value = value;
|
| 918 |
+
}
|
| 919 |
+
}
|
| 920 |
+
|
| 921 |
+
highlightNetworkAnomaly(nodeId) {
|
| 922 |
+
const nodes = this.securityObjects.get('network_nodes');
|
| 923 |
+
if (nodes && nodes[nodeId]) {
|
| 924 |
+
const node = nodes[nodeId];
|
| 925 |
+
node.material.color.setHex(0xff0000);
|
| 926 |
+
node.material.emissive.setHex(0xff0000);
|
| 927 |
+
node.material.emissiveIntensity = 0.5;
|
| 928 |
+
|
| 929 |
+
// Reset after 3 seconds
|
| 930 |
+
setTimeout(() => {
|
| 931 |
+
node.material.color.setHex(0x00e0d5);
|
| 932 |
+
node.material.emissive.setHex(0x00e0d5);
|
| 933 |
+
node.material.emissiveIntensity = 0.3;
|
| 934 |
+
}, 3000);
|
| 935 |
+
}
|
| 936 |
+
}
|
| 937 |
+
|
| 938 |
+
getUserInteractions() {
|
| 939 |
+
return this.userInteractions;
|
| 940 |
+
}
|
| 941 |
+
|
| 942 |
+
dispose() {
|
| 943 |
+
if (this.animationId) {
|
| 944 |
+
cancelAnimationFrame(this.animationId);
|
| 945 |
+
}
|
| 946 |
+
|
| 947 |
+
if (this.renderer) {
|
| 948 |
+
this.renderer.dispose();
|
| 949 |
+
}
|
| 950 |
+
|
| 951 |
+
if (this.controls) {
|
| 952 |
+
// Clean up controls
|
| 953 |
+
}
|
| 954 |
+
}
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
/**
|
| 958 |
+
* Gesture Recognition System
|
| 959 |
+
*/
|
| 960 |
+
class GestureRecognizer {
|
| 961 |
+
constructor() {
|
| 962 |
+
this.touches = [];
|
| 963 |
+
this.gestures = [];
|
| 964 |
+
this.initialized = false;
|
| 965 |
+
}
|
| 966 |
+
|
| 967 |
+
async initialize() {
|
| 968 |
+
console.log('👋 Initializing gesture recognition...');
|
| 969 |
+
this.initialized = true;
|
| 970 |
+
}
|
| 971 |
+
|
| 972 |
+
onGesture(callback) {
|
| 973 |
+
this.gestureCallback = callback;
|
| 974 |
+
}
|
| 975 |
+
|
| 976 |
+
addTouch(touch) {
|
| 977 |
+
this.touches.push(touch);
|
| 978 |
+
this.detectGestures();
|
| 979 |
+
}
|
| 980 |
+
|
| 981 |
+
removeTouch(touchId) {
|
| 982 |
+
this.touches = this.touches.filter(t => t.id !== touchId);
|
| 983 |
+
}
|
| 984 |
+
|
| 985 |
+
detectGestures() {
|
| 986 |
+
if (this.touches.length === 1) {
|
| 987 |
+
// Single touch gestures
|
| 988 |
+
} else if (this.touches.length === 2) {
|
| 989 |
+
// Pinch gesture
|
| 990 |
+
this.detectPinch();
|
| 991 |
+
}
|
| 992 |
+
}
|
| 993 |
+
|
| 994 |
+
detectPinch() {
|
| 995 |
+
if (this.touches.length === 2) {
|
| 996 |
+
const touch1 = this.touches[0];
|
| 997 |
+
const touch2 = this.touches[1];
|
| 998 |
+
const distance = Math.sqrt(
|
| 999 |
+
Math.pow(touch2.x - touch1.x, 2) + Math.pow(touch2.y - touch1.y, 2)
|
| 1000 |
+
);
|
| 1001 |
+
|
| 1002 |
+
if (this.lastPinchDistance) {
|
| 1003 |
+
const scale = distance / this.lastPinchDistance;
|
| 1004 |
+
if (Math.abs(scale - 1) > 0.1) {
|
| 1005 |
+
this.gestureCallback({
|
| 1006 |
+
type: 'pinch',
|
| 1007 |
+
scale: scale,
|
| 1008 |
+
timestamp: Date.now()
|
| 1009 |
+
});
|
| 1010 |
+
}
|
| 1011 |
+
}
|
| 1012 |
+
|
| 1013 |
+
this.lastPinchDistance = distance;
|
| 1014 |
+
}
|
| 1015 |
+
}
|
| 1016 |
+
}
|
| 1017 |
+
|
| 1018 |
+
/**
|
| 1019 |
+
* Touch Handler
|
| 1020 |
+
*/
|
| 1021 |
+
class TouchHandler {
|
| 1022 |
+
constructor() {
|
| 1023 |
+
this.touches = new Map();
|
| 1024 |
+
}
|
| 1025 |
+
|
| 1026 |
+
initialize(element) {
|
| 1027 |
+
element.addEventListener('touchstart', (e) => this.handleTouchStart(e));
|
| 1028 |
+
element.addEventListener('touchmove', (e) => this.handleTouchMove(e));
|
| 1029 |
+
element.addEventListener('touchend', (e) => this.handleTouchEnd(e));
|
| 1030 |
+
}
|
| 1031 |
+
|
| 1032 |
+
handleTouchStart(e) {
|
| 1033 |
+
e.preventDefault();
|
| 1034 |
+
for (let i = 0; i < e.changedTouches.length; i++) {
|
| 1035 |
+
const touch = e.changedTouches[i];
|
| 1036 |
+
this.touches.set(touch.identifier, {
|
| 1037 |
+
id: touch.identifier,
|
| 1038 |
+
x: touch.clientX,
|
| 1039 |
+
y: touch.clientY,
|
| 1040 |
+
startX: touch.clientX,
|
| 1041 |
+
startY: touch.clientY
|
| 1042 |
+
});
|
| 1043 |
+
}
|
| 1044 |
+
}
|
| 1045 |
+
|
| 1046 |
+
handleTouchMove(e) {
|
| 1047 |
+
e.preventDefault();
|
| 1048 |
+
for (let i = 0; i < e.changedTouches.length; i++) {
|
| 1049 |
+
const touch = e.changedTouches[i];
|
| 1050 |
+
if (this.touches.has(touch.identifier)) {
|
| 1051 |
+
const stored = this.touches.get(touch.identifier);
|
| 1052 |
+
stored.x = touch.clientX;
|
| 1053 |
+
stored.y = touch.clientY;
|
| 1054 |
+
}
|
| 1055 |
+
}
|
| 1056 |
+
}
|
| 1057 |
+
|
| 1058 |
+
handleTouchEnd(e) {
|
| 1059 |
+
e.preventDefault();
|
| 1060 |
+
for (let i = 0; i < e.changedTouches.length; i++) {
|
| 1061 |
+
const touch = e.changedTouches[i];
|
| 1062 |
+
this.touches.delete(touch.identifier);
|
| 1063 |
+
}
|
| 1064 |
+
}
|
| 1065 |
+
}
|
| 1066 |
+
|
| 1067 |
+
/**
|
| 1068 |
+
* Security Visualization Helper
|
| 1069 |
+
*/
|
| 1070 |
+
class SecurityVisualization {
|
| 1071 |
+
createThreatVisualization(threatData) {
|
| 1072 |
+
// Create threat visualization based on data
|
| 1073 |
+
return {
|
| 1074 |
+
threats: threatData,
|
| 1075 |
+
visualization: '3d_sphere',
|
| 1076 |
+
animation: 'pulse'
|
| 1077 |
+
};
|
| 1078 |
+
}
|
| 1079 |
+
}
|
| 1080 |
+
|
| 1081 |
+
// Export for use in other modules
|
| 1082 |
+
if (typeof module !== 'undefined' && module.exports) {
|
| 1083 |
+
module.exports = {
|
| 1084 |
+
Security3DInterface,
|
| 1085 |
+
GestureRecognizer,
|
| 1086 |
+
TouchHandler,
|
| 1087 |
+
SecurityVisualization
|
| 1088 |
+
};
|
| 1089 |
+
}
|
js/advanced-vulnerability-detector.js
ADDED
|
@@ -0,0 +1,1344 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* Advanced Vulnerability Detection System
|
| 3 |
+
* NLP-powered vulnerability detection with pattern recognition and machine learning
|
| 4 |
+
* Author: MiniMax Agent
|
| 5 |
+
* Date: 2025-12-10
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
class AdvancedVulnerabilityDetector {
|
| 9 |
+
constructor() {
|
| 10 |
+
this.nlpEngine = new NLPVulnerabilityEngine();
|
| 11 |
+
this.patternRecognizer = new AdvancedPatternRecognizer();
|
| 12 |
+
this.mlClassifier = new MLVulnerabilityClassifier();
|
| 13 |
+
this.semanticAnalyzer = new SemanticCodeAnalyzer();
|
| 14 |
+
this.contextAnalyzer = new ContextualAnalyzer();
|
| 15 |
+
this.initialized = false;
|
| 16 |
+
this.detectionCache = new Map();
|
| 17 |
+
this.learningData = [];
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
async initialize() {
|
| 21 |
+
try {
|
| 22 |
+
console.log('🔍 Initializing Advanced Vulnerability Detector...');
|
| 23 |
+
|
| 24 |
+
// Initialize NLP engine
|
| 25 |
+
await this.nlpEngine.initialize();
|
| 26 |
+
|
| 27 |
+
// Initialize pattern recognition
|
| 28 |
+
await this.patternRecognizer.initialize();
|
| 29 |
+
|
| 30 |
+
// Initialize ML classifier
|
| 31 |
+
await this.mlClassifier.initialize();
|
| 32 |
+
|
| 33 |
+
// Initialize semantic analyzer
|
| 34 |
+
await this.semanticAnalyzer.initialize();
|
| 35 |
+
|
| 36 |
+
// Initialize context analyzer
|
| 37 |
+
await this.contextAnalyzer.initialize();
|
| 38 |
+
|
| 39 |
+
// Load vulnerability knowledge base
|
| 40 |
+
await this.loadVulnerabilityKnowledgeBase();
|
| 41 |
+
|
| 42 |
+
// Setup real-time monitoring
|
| 43 |
+
this.setupRealTimeDetection();
|
| 44 |
+
|
| 45 |
+
this.initialized = true;
|
| 46 |
+
console.log('✅ Advanced Vulnerability Detector initialized successfully');
|
| 47 |
+
|
| 48 |
+
} catch (error) {
|
| 49 |
+
console.error('❌ Failed to initialize Advanced Vulnerability Detector:', error);
|
| 50 |
+
throw error;
|
| 51 |
+
}
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
async loadVulnerabilityKnowledgeBase() {
|
| 55 |
+
this.vulnerabilityPatterns = {
|
| 56 |
+
sql_injection: {
|
| 57 |
+
patterns: [
|
| 58 |
+
/union\s+select/gi,
|
| 59 |
+
/['"]\s*or\s*['"]1['"]\s*=\s*['"]1['"]/gi,
|
| 60 |
+
/\b(drop|delete|update|insert)\s+table/gi,
|
| 61 |
+
/\b(exec|execute)\s*\(/gi,
|
| 62 |
+
/--\s*$/gm,
|
| 63 |
+
/\bshutdown\b/gi,
|
| 64 |
+
/\b xp_cmdshell \b/gi
|
| 65 |
+
],
|
| 66 |
+
semantic: {
|
| 67 |
+
keywords: ['sql', 'database', 'query', 'select', 'insert', 'update', 'delete'],
|
| 68 |
+
context: ['user_input', 'parameter', 'request', 'form'],
|
| 69 |
+
severity: 9
|
| 70 |
+
},
|
| 71 |
+
variants: [
|
| 72 |
+
'union-based injection',
|
| 73 |
+
'boolean-based injection',
|
| 74 |
+
'time-based injection',
|
| 75 |
+
'error-based injection',
|
| 76 |
+
'stacked queries injection'
|
| 77 |
+
]
|
| 78 |
+
},
|
| 79 |
+
|
| 80 |
+
xss: {
|
| 81 |
+
patterns: [
|
| 82 |
+
/<script\b[^>]*>.*?<\/script>/gi,
|
| 83 |
+
/<iframe\b[^>]*>/gi,
|
| 84 |
+
/\bon\w+\s*=\s*["'][^"']*["']/gi,
|
| 85 |
+
/javascript:/gi,
|
| 86 |
+
/\beval\s*\(/gi,
|
| 87 |
+
/\bdocument\.(cookie|location)\b/gi,
|
| 88 |
+
/\bwindow\.(location|open)\b/gi
|
| 89 |
+
],
|
| 90 |
+
semantic: {
|
| 91 |
+
keywords: ['html', 'script', 'javascript', 'event', 'onclick', 'onload'],
|
| 92 |
+
context: ['output', 'display', 'render', 'innerHTML', 'document.write'],
|
| 93 |
+
severity: 8
|
| 94 |
+
},
|
| 95 |
+
variants: [
|
| 96 |
+
'reflected XSS',
|
| 97 |
+
'stored XSS',
|
| 98 |
+
'DOM-based XSS',
|
| 99 |
+
'mXSS (mutated XSS)',
|
| 100 |
+
'Universal XSS (UXSS)'
|
| 101 |
+
]
|
| 102 |
+
},
|
| 103 |
+
|
| 104 |
+
command_injection: {
|
| 105 |
+
patterns: [
|
| 106 |
+
/[;&|`$]\s*(?:ls|cat|rm|mkdir|chmod|chown|wget|curl|nc|netcat|telnet|ssh)/gi,
|
| 107 |
+
/\bexec\s*\(\s*\$_(?:GET|POST|REQUEST)\[/gi,
|
| 108 |
+
/\bshell_exec\s*\(/gi,
|
| 109 |
+
/\bsystem\s*\(/gi,
|
| 110 |
+
/\bpopen\s*\(/gi,
|
| 111 |
+
/`[^`]*`/gi
|
| 112 |
+
],
|
| 113 |
+
semantic: {
|
| 114 |
+
keywords: ['exec', 'system', 'shell', 'command', 'bash', 'cmd'],
|
| 115 |
+
context: ['system', 'shell', 'os', 'command', 'execute'],
|
| 116 |
+
severity: 10
|
| 117 |
+
},
|
| 118 |
+
variants: [
|
| 119 |
+
'OS Command Injection',
|
| 120 |
+
'Shell Injection',
|
| 121 |
+
'Code Injection',
|
| 122 |
+
'LDAP Injection',
|
| 123 |
+
'XPath Injection'
|
| 124 |
+
]
|
| 125 |
+
},
|
| 126 |
+
|
| 127 |
+
path_traversal: {
|
| 128 |
+
patterns: [
|
| 129 |
+
/\.\.[\/\\]/gi,
|
| 130 |
+
/%2e%2e%2f/gi,
|
| 131 |
+
/%252e%252e%252f/gi,
|
| 132 |
+
/\.\.%2f/gi,
|
| 133 |
+
/etc\/passwd/gi,
|
| 134 |
+
/boot\.ini/gi,
|
| 135 |
+
/windows\/system32/gi
|
| 136 |
+
],
|
| 137 |
+
semantic: {
|
| 138 |
+
keywords: ['path', 'file', 'directory', 'folder', 'read', 'open'],
|
| 139 |
+
context: ['file_path', 'directory', 'include', 'require', 'import'],
|
| 140 |
+
severity: 8
|
| 141 |
+
},
|
| 142 |
+
variants: [
|
| 143 |
+
'Directory Traversal',
|
| 144 |
+
'Path Traversal',
|
| 145 |
+
'File Inclusion',
|
| 146 |
+
'Null Byte Injection',
|
| 147 |
+
'Unicode Traversal'
|
| 148 |
+
]
|
| 149 |
+
},
|
| 150 |
+
|
| 151 |
+
csrf: {
|
| 152 |
+
patterns: [
|
| 153 |
+
/<form[^>]*method\s*=\s*["']?(?:post|put|delete)["']?[^>]*>/gi,
|
| 154 |
+
/\b(csrf_token|xsrf_token)\b/gi,
|
| 155 |
+
/\breferer\s*=/gi,
|
| 156 |
+
/\borigin\s*=/gi,
|
| 157 |
+
/\bwithCredentials\s*=/gi
|
| 158 |
+
],
|
| 159 |
+
semantic: {
|
| 160 |
+
keywords: ['form', 'post', 'token', 'validate', 'verify'],
|
| 161 |
+
context: ['form', 'request', 'action', 'submit', 'method'],
|
| 162 |
+
severity: 7
|
| 163 |
+
},
|
| 164 |
+
variants: [
|
| 165 |
+
'Login CSRF',
|
| 166 |
+
'Session Fixation',
|
| 167 |
+
'Cross-Site Request Forgery',
|
| 168 |
+
'One-Click Attack',
|
| 169 |
+
'Smart CSRF'
|
| 170 |
+
]
|
| 171 |
+
},
|
| 172 |
+
|
| 173 |
+
deserialization: {
|
| 174 |
+
patterns: [
|
| 175 |
+
/\b(unserialize|json_decode|yaml_parse|pickle_loads)\s*\(/gi,
|
| 176 |
+
/\bphar:\/\//gi,
|
| 177 |
+
/O:\d+:/gi,
|
| 178 |
+
/a:\d+:/gi,
|
| 179 |
+
/\b@eval\s*\(/gi,
|
| 180 |
+
/\b__wakeup\b/gi,
|
| 181 |
+
/\b__destruct\b/gi
|
| 182 |
+
],
|
| 183 |
+
semantic: {
|
| 184 |
+
keywords: ['serialize', 'deserialize', 'pickle', 'unserialize', 'object'],
|
| 185 |
+
context: ['object', 'class', 'method', 'function', 'callback'],
|
| 186 |
+
severity: 9
|
| 187 |
+
},
|
| 188 |
+
variants: [
|
| 189 |
+
'PHP Deserialization',
|
| 190 |
+
'Python Pickle Injection',
|
| 191 |
+
'Java Deserialization',
|
| 192 |
+
'.NET Deserialization',
|
| 193 |
+
'Ruby YAML Deserialization'
|
| 194 |
+
]
|
| 195 |
+
},
|
| 196 |
+
|
| 197 |
+
server_side_request_forgery: {
|
| 198 |
+
patterns: [
|
| 199 |
+
/\b(file_get_contents|curl_exec|wget|fsockopen)\s*\(\s*\$_(?:GET|POST|REQUEST)/gi,
|
| 200 |
+
/\b(urlopen|urlretrieve)\s*\(/gi,
|
| 201 |
+
/\b(HttpRequest|WebClient)\s*\(/gi,
|
| 202 |
+
/https?:\/\/localhost/gi,
|
| 203 |
+
/file:\/\//gi,
|
| 204 |
+
/dict:\/\//gi
|
| 205 |
+
],
|
| 206 |
+
semantic: {
|
| 207 |
+
keywords: ['request', 'url', 'fetch', 'get', 'download', 'include'],
|
| 208 |
+
context: ['http', 'request', 'url', 'fetch', 'download'],
|
| 209 |
+
severity: 9
|
| 210 |
+
},
|
| 211 |
+
variants: [
|
| 212 |
+
'Basic SSRF',
|
| 213 |
+
'Blind SSRF',
|
| 214 |
+
'Semi-Blind SSRF',
|
| 215 |
+
'XXE (XML External Entity)',
|
| 216 |
+
'Open Redirect'
|
| 217 |
+
]
|
| 218 |
+
}
|
| 219 |
+
};
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
async analyzeCode(code, options = {}) {
|
| 223 |
+
if (!this.initialized) {
|
| 224 |
+
await this.initialize();
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
const analysisId = this.generateAnalysisId(code);
|
| 228 |
+
|
| 229 |
+
// Check cache first
|
| 230 |
+
if (this.detectionCache.has(analysisId) && !options.force) {
|
| 231 |
+
console.log('📋 Returning cached analysis result');
|
| 232 |
+
return this.detectionCache.get(analysisId);
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
console.log('🔍 Starting comprehensive vulnerability analysis...');
|
| 236 |
+
|
| 237 |
+
const analysisResults = {
|
| 238 |
+
id: analysisId,
|
| 239 |
+
timestamp: Date.now(),
|
| 240 |
+
code: code,
|
| 241 |
+
vulnerabilities: [],
|
| 242 |
+
riskScore: 0,
|
| 243 |
+
confidence: 0,
|
| 244 |
+
recommendations: [],
|
| 245 |
+
analysisTime: 0,
|
| 246 |
+
methods: []
|
| 247 |
+
};
|
| 248 |
+
|
| 249 |
+
const startTime = performance.now();
|
| 250 |
+
|
| 251 |
+
try {
|
| 252 |
+
// Multi-method analysis
|
| 253 |
+
const [
|
| 254 |
+
patternResults,
|
| 255 |
+
semanticResults,
|
| 256 |
+
contextualResults,
|
| 257 |
+
mlResults,
|
| 258 |
+
nlpResults
|
| 259 |
+
] = await Promise.allSettled([
|
| 260 |
+
this.patternRecognizer.analyze(code, this.vulnerabilityPatterns),
|
| 261 |
+
this.semanticAnalyzer.analyze(code),
|
| 262 |
+
this.contextAnalyzer.analyze(code),
|
| 263 |
+
this.mlClassifier.classify(code),
|
| 264 |
+
this.nlpEngine.analyze(code)
|
| 265 |
+
]);
|
| 266 |
+
|
| 267 |
+
// Process results
|
| 268 |
+
if (patternResults.status === 'fulfilled') {
|
| 269 |
+
analysisResults.vulnerabilities.push(...patternResults.value);
|
| 270 |
+
analysisResults.methods.push('pattern_recognition');
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
if (semanticResults.status === 'fulfilled') {
|
| 274 |
+
analysisResults.vulnerabilities.push(...semanticResults.value);
|
| 275 |
+
analysisResults.methods.push('semantic_analysis');
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
if (contextualResults.status === 'fulfilled') {
|
| 279 |
+
analysisResults.vulnerabilities.push(...contextualResults.value);
|
| 280 |
+
analysisResults.methods.push('contextual_analysis');
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
if (mlResults.status === 'fulfilled') {
|
| 284 |
+
analysisResults.vulnerabilities.push(...mlResults.value);
|
| 285 |
+
analysisResults.methods.push('machine_learning');
|
| 286 |
+
}
|
| 287 |
+
|
| 288 |
+
if (nlpResults.status === 'fulfilled') {
|
| 289 |
+
analysisResults.vulnerabilities.push(...nlpResults.value);
|
| 290 |
+
analysisResults.methods.push('nlp_analysis');
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
// Deduplicate vulnerabilities
|
| 294 |
+
analysisResults.vulnerabilities = this.deduplicateVulnerabilities(
|
| 295 |
+
analysisResults.vulnerabilities
|
| 296 |
+
);
|
| 297 |
+
|
| 298 |
+
// Calculate overall risk score
|
| 299 |
+
analysisResults.riskScore = this.calculateRiskScore(analysisResults.vulnerabilities);
|
| 300 |
+
|
| 301 |
+
// Calculate confidence
|
| 302 |
+
analysisResults.confidence = this.calculateConfidence(analysisResults);
|
| 303 |
+
|
| 304 |
+
// Generate recommendations
|
| 305 |
+
analysisResults.recommendations = this.generateRecommendations(
|
| 306 |
+
analysisResults.vulnerabilities
|
| 307 |
+
);
|
| 308 |
+
|
| 309 |
+
const endTime = performance.now();
|
| 310 |
+
analysisResults.analysisTime = endTime - startTime;
|
| 311 |
+
|
| 312 |
+
// Cache results
|
| 313 |
+
this.detectionCache.set(analysisId, analysisResults);
|
| 314 |
+
|
| 315 |
+
// Store for learning
|
| 316 |
+
this.learningData.push({
|
| 317 |
+
code: code,
|
| 318 |
+
vulnerabilities: analysisResults.vulnerabilities,
|
| 319 |
+
timestamp: Date.now()
|
| 320 |
+
});
|
| 321 |
+
|
| 322 |
+
console.log(`✅ Analysis completed in ${analysisResults.analysisTime.toFixed(2)}ms`);
|
| 323 |
+
return analysisResults;
|
| 324 |
+
|
| 325 |
+
} catch (error) {
|
| 326 |
+
console.error('Analysis failed:', error);
|
| 327 |
+
throw new Error(`Vulnerability analysis failed: ${error.message}`);
|
| 328 |
+
}
|
| 329 |
+
}
|
| 330 |
+
|
| 331 |
+
deduplicateVulnerabilities(vulnerabilities) {
|
| 332 |
+
const seen = new Set();
|
| 333 |
+
return vulnerabilities.filter(vuln => {
|
| 334 |
+
const key = `${vuln.type}-${vuln.line}-${vuln.startColumn}-${vuln.endColumn}`;
|
| 335 |
+
if (seen.has(key)) {
|
| 336 |
+
return false;
|
| 337 |
+
}
|
| 338 |
+
seen.add(key);
|
| 339 |
+
return true;
|
| 340 |
+
});
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
calculateRiskScore(vulnerabilities) {
|
| 344 |
+
if (vulnerabilities.length === 0) return 0;
|
| 345 |
+
|
| 346 |
+
const weightedScore = vulnerabilities.reduce((score, vuln) => {
|
| 347 |
+
const baseScore = vuln.severity || 5;
|
| 348 |
+
const confidenceMultiplier = vuln.confidence || 0.5;
|
| 349 |
+
const contextMultiplier = vuln.contextScore || 1;
|
| 350 |
+
|
| 351 |
+
return score + (baseScore * confidenceMultiplier * contextMultiplier);
|
| 352 |
+
}, 0);
|
| 353 |
+
|
| 354 |
+
return Math.min(100, weightedScore);
|
| 355 |
+
}
|
| 356 |
+
|
| 357 |
+
calculateConfidence(analysisResults) {
|
| 358 |
+
const methodCount = analysisResults.methods.length;
|
| 359 |
+
const vulnerabilityCount = analysisResults.vulnerabilities.length;
|
| 360 |
+
const avgConfidence = analysisResults.vulnerabilities.reduce(
|
| 361 |
+
(sum, vuln) => sum + (vuln.confidence || 0.5), 0
|
| 362 |
+
) / Math.max(vulnerabilityCount, 1);
|
| 363 |
+
|
| 364 |
+
// Higher confidence with multiple methods agreeing
|
| 365 |
+
const methodBonus = Math.min(0.3, (methodCount - 1) * 0.1);
|
| 366 |
+
|
| 367 |
+
return Math.min(0.99, avgConfidence + methodBonus);
|
| 368 |
+
}
|
| 369 |
+
|
| 370 |
+
generateRecommendations(vulnerabilities) {
|
| 371 |
+
const recommendations = [];
|
| 372 |
+
const vulnTypes = [...new Set(vulnerabilities.map(v => v.type))];
|
| 373 |
+
|
| 374 |
+
for (const vulnType of vulnTypes) {
|
| 375 |
+
const vulnGroup = vulnerabilities.filter(v => v.type === vulnType);
|
| 376 |
+
const maxSeverity = Math.max(...vulnGroup.map(v => v.severity || 5));
|
| 377 |
+
|
| 378 |
+
switch (vulnType) {
|
| 379 |
+
case 'sql_injection':
|
| 380 |
+
recommendations.push({
|
| 381 |
+
type: 'SQL Injection Prevention',
|
| 382 |
+
priority: maxSeverity >= 8 ? 'Critical' : 'High',
|
| 383 |
+
actions: [
|
| 384 |
+
'Use parameterized queries for all database operations',
|
| 385 |
+
'Implement input validation and sanitization',
|
| 386 |
+
'Use ORM frameworks when possible',
|
| 387 |
+
'Apply principle of least privilege for database accounts'
|
| 388 |
+
],
|
| 389 |
+
code: `// Safe example
|
| 390 |
+
const query = 'SELECT * FROM users WHERE id = ? AND password_hash = ?';
|
| 391 |
+
const result = db.execute(query, [userId, passwordHash]);`
|
| 392 |
+
});
|
| 393 |
+
break;
|
| 394 |
+
|
| 395 |
+
case 'xss':
|
| 396 |
+
recommendations.push({
|
| 397 |
+
type: 'XSS Prevention',
|
| 398 |
+
priority: maxSeverity >= 8 ? 'Critical' : 'High',
|
| 399 |
+
actions: [
|
| 400 |
+
'Implement Content Security Policy (CSP)',
|
| 401 |
+
'Use output encoding for all user data',
|
| 402 |
+
'Avoid innerHTML for user content',
|
| 403 |
+
'Use textContent instead of innerHTML',
|
| 404 |
+
'Validate and sanitize all inputs'
|
| 405 |
+
],
|
| 406 |
+
code: `// Safe example
|
| 407 |
+
element.textContent = userInput; // Instead of element.innerHTML = userInput
|
| 408 |
+
|
| 409 |
+
// CSP header
|
| 410 |
+
Content-Security-Policy: default-src 'self'; script-src 'self';`
|
| 411 |
+
});
|
| 412 |
+
break;
|
| 413 |
+
|
| 414 |
+
case 'command_injection':
|
| 415 |
+
recommendations.push({
|
| 416 |
+
type: 'Command Injection Prevention',
|
| 417 |
+
priority: 'Critical',
|
| 418 |
+
actions: [
|
| 419 |
+
'Avoid shell command execution with user input',
|
| 420 |
+
'Use APIs instead of system calls when possible',
|
| 421 |
+
'Implement strict input validation',
|
| 422 |
+
'Use allowlists instead of blocklists',
|
| 423 |
+
'Escape shell metacharacters'
|
| 424 |
+
],
|
| 425 |
+
code: `// Safe example - avoid
|
| 426 |
+
// system("ls " + userInput); // UNSAFE
|
| 427 |
+
|
| 428 |
+
// Instead use
|
| 429 |
+
const allowedCommands = ['list', 'info', 'status'];
|
| 430 |
+
if (allowedCommands.includes(userInput)) {
|
| 431 |
+
executeCommand(userInput);
|
| 432 |
+
}`
|
| 433 |
+
});
|
| 434 |
+
break;
|
| 435 |
+
|
| 436 |
+
case 'csrf':
|
| 437 |
+
recommendations.push({
|
| 438 |
+
type: 'CSRF Prevention',
|
| 439 |
+
priority: 'High',
|
| 440 |
+
actions: [
|
| 441 |
+
'Implement CSRF tokens for all state-changing operations',
|
| 442 |
+
'Use SameSite cookies',
|
| 443 |
+
'Validate Referer and Origin headers',
|
| 444 |
+
'Use POST for state-changing operations',
|
| 445 |
+
'Implement rate limiting'
|
| 446 |
+
],
|
| 447 |
+
code: `// Safe example
|
| 448 |
+
// Generate CSRF token
|
| 449 |
+
const csrfToken = generateSecureToken();
|
| 450 |
+
|
| 451 |
+
// Include in forms
|
| 452 |
+
<form method="POST">
|
| 453 |
+
<input type="hidden" name="csrf_token" value="${csrfToken}">
|
| 454 |
+
</form>
|
| 455 |
+
|
| 456 |
+
// Validate on server
|
| 457 |
+
if (!validateCSRFToken(request.csrf_token, session.csrf_token)) {
|
| 458 |
+
throw new Error('Invalid CSRF token');
|
| 459 |
+
}`
|
| 460 |
+
});
|
| 461 |
+
break;
|
| 462 |
+
|
| 463 |
+
case 'deserialization':
|
| 464 |
+
recommendations.push({
|
| 465 |
+
type: 'Deserialization Prevention',
|
| 466 |
+
priority: 'Critical',
|
| 467 |
+
actions: [
|
| 468 |
+
'Avoid deserializing untrusted data',
|
| 469 |
+
'Use safe serialization formats (JSON)',
|
| 470 |
+
'Implement integrity checks',
|
| 471 |
+
'Validate object types before deserialization',
|
| 472 |
+
'Use type-safe deserialization libraries'
|
| 473 |
+
],
|
| 474 |
+
code: `// Safe example
|
| 475 |
+
// Instead of unsafe deserialization
|
| 476 |
+
// unserialize(userInput); // UNSAFE
|
| 477 |
+
|
| 478 |
+
// Use JSON
|
| 479 |
+
const data = JSON.parse(userInput); // Safe
|
| 480 |
+
|
| 481 |
+
// For PHP, use safe deserialization
|
| 482 |
+
$object = Symfony\Component\Yaml\Yaml::parse($userInput);`
|
| 483 |
+
});
|
| 484 |
+
break;
|
| 485 |
+
}
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
return recommendations;
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
generateAnalysisId(code) {
|
| 492 |
+
return 'analysis_' + this.simpleHash(code);
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
simpleHash(str) {
|
| 496 |
+
let hash = 0;
|
| 497 |
+
for (let i = 0; i < str.length; i++) {
|
| 498 |
+
const char = str.charCodeAt(i);
|
| 499 |
+
hash = ((hash << 5) - hash) + char;
|
| 500 |
+
hash = hash & hash; // Convert to 32bit integer
|
| 501 |
+
}
|
| 502 |
+
return Math.abs(hash).toString(36);
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
setupRealTimeDetection() {
|
| 506 |
+
// Monitor for new vulnerabilities in real-time
|
| 507 |
+
if (typeof window !== 'undefined') {
|
| 508 |
+
// Monitor DOM changes
|
| 509 |
+
const observer = new MutationObserver((mutations) => {
|
| 510 |
+
mutations.forEach((mutation) => {
|
| 511 |
+
mutation.addedNodes.forEach((node) => {
|
| 512 |
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
| 513 |
+
this.analyzeElement(node);
|
| 514 |
+
}
|
| 515 |
+
});
|
| 516 |
+
});
|
| 517 |
+
});
|
| 518 |
+
|
| 519 |
+
observer.observe(document.body, {
|
| 520 |
+
childList: true,
|
| 521 |
+
subtree: true
|
| 522 |
+
});
|
| 523 |
+
|
| 524 |
+
// Monitor script injection
|
| 525 |
+
const originalCreateElement = document.createElement;
|
| 526 |
+
document.createElement = function(tagName) {
|
| 527 |
+
const element = originalCreateElement.call(this, tagName);
|
| 528 |
+
if (tagName.toLowerCase() === 'script') {
|
| 529 |
+
this.analyzeElement(element);
|
| 530 |
+
}
|
| 531 |
+
return element;
|
| 532 |
+
};
|
| 533 |
+
}
|
| 534 |
+
}
|
| 535 |
+
|
| 536 |
+
async analyzeElement(element) {
|
| 537 |
+
const html = element.outerHTML || '';
|
| 538 |
+
if (html.length > 0) {
|
| 539 |
+
try {
|
| 540 |
+
const results = await this.analyzeCode(html, { force: true });
|
| 541 |
+
if (results.vulnerabilities.length > 0) {
|
| 542 |
+
console.warn('🚨 Real-time vulnerability detected:', results.vulnerabilities);
|
| 543 |
+
this.handleRealTimeVulnerability(results);
|
| 544 |
+
}
|
| 545 |
+
} catch (error) {
|
| 546 |
+
// Silent fail for real-time analysis
|
| 547 |
+
}
|
| 548 |
+
}
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
handleRealTimeVulnerability(results) {
|
| 552 |
+
// Dispatch custom event for real-time vulnerability detection
|
| 553 |
+
if (typeof window !== 'undefined' && window.dispatchEvent) {
|
| 554 |
+
window.dispatchEvent(new CustomEvent('vulnerabilityDetected', {
|
| 555 |
+
detail: results
|
| 556 |
+
}));
|
| 557 |
+
}
|
| 558 |
+
}
|
| 559 |
+
|
| 560 |
+
// Public API methods
|
| 561 |
+
async getVulnerabilityPatterns() {
|
| 562 |
+
return this.vulnerabilityPatterns;
|
| 563 |
+
}
|
| 564 |
+
|
| 565 |
+
async getAnalysisHistory() {
|
| 566 |
+
return Array.from(this.detectionCache.values());
|
| 567 |
+
}
|
| 568 |
+
|
| 569 |
+
async exportResults(format = 'json') {
|
| 570 |
+
const results = Array.from(this.detectionCache.values());
|
| 571 |
+
|
| 572 |
+
switch (format) {
|
| 573 |
+
case 'json':
|
| 574 |
+
return JSON.stringify(results, null, 2);
|
| 575 |
+
case 'csv':
|
| 576 |
+
return this.convertToCSV(results);
|
| 577 |
+
case 'html':
|
| 578 |
+
return this.convertToHTML(results);
|
| 579 |
+
default:
|
| 580 |
+
return JSON.stringify(results, null, 2);
|
| 581 |
+
}
|
| 582 |
+
}
|
| 583 |
+
|
| 584 |
+
convertToCSV(results) {
|
| 585 |
+
const headers = ['ID', 'Timestamp', 'Risk Score', 'Confidence', 'Vulnerabilities', 'Methods'];
|
| 586 |
+
const rows = results.map(result => [
|
| 587 |
+
result.id,
|
| 588 |
+
new Date(result.timestamp).toISOString(),
|
| 589 |
+
result.riskScore,
|
| 590 |
+
result.confidence,
|
| 591 |
+
result.vulnerabilities.length,
|
| 592 |
+
result.methods.join(';')
|
| 593 |
+
]);
|
| 594 |
+
|
| 595 |
+
return [headers, ...rows].map(row => row.join(',')).join('\n');
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
convertToHTML(results) {
|
| 599 |
+
let html = `
|
| 600 |
+
<!DOCTYPE html>
|
| 601 |
+
<html dir="rtl" lang="ar">
|
| 602 |
+
<head>
|
| 603 |
+
<meta charset="UTF-8">
|
| 604 |
+
<title>نتائج تحليل الثغرات الأمنية</title>
|
| 605 |
+
<style>
|
| 606 |
+
body { font-family: Arial, sans-serif; margin: 20px; }
|
| 607 |
+
.vulnerability { border: 1px solid #ccc; margin: 10px 0; padding: 15px; border-radius: 5px; }
|
| 608 |
+
.critical { border-color: #ff0000; background-color: #ffe6e6; }
|
| 609 |
+
.high { border-color: #ff8800; background-color: #fff0e6; }
|
| 610 |
+
.medium { border-color: #ffff00; background-color: #ffffe6; }
|
| 611 |
+
.low { border-color: #00ff00; background-color: #e6ffe6; }
|
| 612 |
+
.severity { font-weight: bold; }
|
| 613 |
+
</style>
|
| 614 |
+
</head>
|
| 615 |
+
<body>
|
| 616 |
+
<h1>نتائج تحليل الثغرات الأمنية</h1>
|
| 617 |
+
<p>تم إنشاء التقرير في: ${new Date().toLocaleString('ar')}</p>
|
| 618 |
+
`;
|
| 619 |
+
|
| 620 |
+
results.forEach(result => {
|
| 621 |
+
html += `<div class="vulnerability">`;
|
| 622 |
+
html += `<h3>التحليل: ${result.id}</h3>`;
|
| 623 |
+
html += `<p><strong>درجة المخاطر:</strong> ${result.riskScore}</p>`;
|
| 624 |
+
html += `<p><strong>مستوى الثقة:</strong> ${(result.confidence * 100).toFixed(1)}%</p>`;
|
| 625 |
+
html += `<p><strong>عدد الثغرات:</strong> ${result.vulnerabilities.length}</p>`;
|
| 626 |
+
html += `<p><strong>طرق التحليل:</strong> ${result.methods.join(', ')}</p>`;
|
| 627 |
+
|
| 628 |
+
if (result.vulnerabilities.length > 0) {
|
| 629 |
+
html += '<h4>الثغرات المكتشفة:</h4><ul>';
|
| 630 |
+
result.vulnerabilities.forEach(vuln => {
|
| 631 |
+
html += `<li>${vuln.type} - الخط ${vuln.line} - الثقة: ${(vuln.confidence * 100).toFixed(1)}%</li>`;
|
| 632 |
+
});
|
| 633 |
+
html += '</ul>';
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
html += `</div>`;
|
| 637 |
+
});
|
| 638 |
+
|
| 639 |
+
html += '</body></html>';
|
| 640 |
+
return html;
|
| 641 |
+
}
|
| 642 |
+
|
| 643 |
+
dispose() {
|
| 644 |
+
this.detectionCache.clear();
|
| 645 |
+
this.learningData = [];
|
| 646 |
+
}
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
/**
|
| 650 |
+
* NLP Vulnerability Engine
|
| 651 |
+
*/
|
| 652 |
+
class NLPVulnerabilityEngine {
|
| 653 |
+
async initialize() {
|
| 654 |
+
console.log('🧠 Initializing NLP Vulnerability Engine...');
|
| 655 |
+
this.vocabulary = this.buildSecurityVocabulary();
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
buildSecurityVocabulary() {
|
| 659 |
+
return {
|
| 660 |
+
dangerous: ['eval', 'exec', 'system', 'shell_exec', 'passthru', 'popen', 'proc_open'],
|
| 661 |
+
sql: ['select', 'insert', 'update', 'delete', 'union', 'drop', 'create', 'alter'],
|
| 662 |
+
xss: ['script', 'javascript', 'onclick', 'onload', 'innerHTML', 'document.write'],
|
| 663 |
+
injection: ['include', 'require', 'file_get_contents', 'curl_exec', 'wget'],
|
| 664 |
+
traversal: ['../', '..\\', '%2e%2e', 'file://', 'dict://']
|
| 665 |
+
};
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
async analyze(code) {
|
| 669 |
+
const results = [];
|
| 670 |
+
const tokens = this.tokenize(code);
|
| 671 |
+
|
| 672 |
+
for (const [category, words] of Object.entries(this.vocabulary)) {
|
| 673 |
+
const matches = this.findContextualMatches(tokens, words, code);
|
| 674 |
+
if (matches.length > 0) {
|
| 675 |
+
results.push(...matches);
|
| 676 |
+
}
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
return results;
|
| 680 |
+
}
|
| 681 |
+
|
| 682 |
+
tokenize(code) {
|
| 683 |
+
return code
|
| 684 |
+
.toLowerCase()
|
| 685 |
+
.replace(/[^\w\s]/g, ' ')
|
| 686 |
+
.split(/\s+/)
|
| 687 |
+
.filter(token => token.length > 0);
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
findContextualMatches(tokens, dangerousWords, originalCode) {
|
| 691 |
+
const results = [];
|
| 692 |
+
|
| 693 |
+
tokens.forEach((token, index) => {
|
| 694 |
+
if (dangerousWords.includes(token)) {
|
| 695 |
+
// Check for contextual indicators
|
| 696 |
+
const context = this.getContext(tokens, index, 3);
|
| 697 |
+
const confidence = this.calculateContextualConfidence(token, context);
|
| 698 |
+
|
| 699 |
+
if (confidence > 0.6) {
|
| 700 |
+
results.push({
|
| 701 |
+
type: this.getVulnerabilityType(token),
|
| 702 |
+
confidence: confidence,
|
| 703 |
+
line: this.getLineNumber(originalCode, token),
|
| 704 |
+
column: this.getColumnNumber(originalCode, token),
|
| 705 |
+
context: context.join(' '),
|
| 706 |
+
method: 'nlp'
|
| 707 |
+
});
|
| 708 |
+
}
|
| 709 |
+
}
|
| 710 |
+
});
|
| 711 |
+
|
| 712 |
+
return results;
|
| 713 |
+
}
|
| 714 |
+
|
| 715 |
+
getContext(tokens, index, windowSize) {
|
| 716 |
+
const start = Math.max(0, index - windowSize);
|
| 717 |
+
const end = Math.min(tokens.length, index + windowSize + 1);
|
| 718 |
+
return tokens.slice(start, end);
|
| 719 |
+
}
|
| 720 |
+
|
| 721 |
+
calculateContextualConfidence(token, context) {
|
| 722 |
+
let confidence = 0.5; // Base confidence
|
| 723 |
+
|
| 724 |
+
// Boost confidence with dangerous context
|
| 725 |
+
const dangerousContext = ['input', 'user', 'request', 'get', 'post', 'param'];
|
| 726 |
+
const hasDangerousContext = context.some(word => dangerousContext.includes(word));
|
| 727 |
+
|
| 728 |
+
if (hasDangerousContext) confidence += 0.3;
|
| 729 |
+
|
| 730 |
+
// Check for assignment patterns
|
| 731 |
+
const assignmentPattern = context.some((word, i) =>
|
| 732 |
+
word === '=' && i > 0 && dangerousContext.includes(context[i-1])
|
| 733 |
+
);
|
| 734 |
+
if (assignmentPattern) confidence += 0.2;
|
| 735 |
+
|
| 736 |
+
return Math.min(0.99, confidence);
|
| 737 |
+
}
|
| 738 |
+
|
| 739 |
+
getVulnerabilityType(token) {
|
| 740 |
+
const typeMap = {
|
| 741 |
+
'eval': 'code_injection',
|
| 742 |
+
'exec': 'command_injection',
|
| 743 |
+
'system': 'command_injection',
|
| 744 |
+
'shell_exec': 'command_injection',
|
| 745 |
+
'select': 'sql_injection',
|
| 746 |
+
'union': 'sql_injection',
|
| 747 |
+
'script': 'xss',
|
| 748 |
+
'javascript': 'xss',
|
| 749 |
+
'onclick': 'xss',
|
| 750 |
+
'innerHTML': 'xss',
|
| 751 |
+
'../': 'path_traversal',
|
| 752 |
+
'..\\': 'path_traversal'
|
| 753 |
+
};
|
| 754 |
+
|
| 755 |
+
return typeMap[token] || 'unknown';
|
| 756 |
+
}
|
| 757 |
+
|
| 758 |
+
getLineNumber(code, token) {
|
| 759 |
+
const lines = code.split('\n');
|
| 760 |
+
for (let i = 0; i < lines.length; i++) {
|
| 761 |
+
if (lines[i].includes(token)) {
|
| 762 |
+
return i + 1;
|
| 763 |
+
}
|
| 764 |
+
}
|
| 765 |
+
return 1;
|
| 766 |
+
}
|
| 767 |
+
|
| 768 |
+
getColumnNumber(code, token) {
|
| 769 |
+
const lines = code.split('\n');
|
| 770 |
+
for (let i = 0; i < lines.length; i++) {
|
| 771 |
+
const column = lines[i].indexOf(token);
|
| 772 |
+
if (column !== -1) {
|
| 773 |
+
return column + 1;
|
| 774 |
+
}
|
| 775 |
+
}
|
| 776 |
+
return 1;
|
| 777 |
+
}
|
| 778 |
+
}
|
| 779 |
+
|
| 780 |
+
/**
|
| 781 |
+
* Advanced Pattern Recognizer
|
| 782 |
+
*/
|
| 783 |
+
class AdvancedPatternRecognizer {
|
| 784 |
+
async initialize() {
|
| 785 |
+
console.log('🎯 Initializing Advanced Pattern Recognizer...');
|
| 786 |
+
}
|
| 787 |
+
|
| 788 |
+
async analyze(code, patterns) {
|
| 789 |
+
const results = [];
|
| 790 |
+
|
| 791 |
+
for (const [vulnType, vulnData] of Object.entries(patterns)) {
|
| 792 |
+
for (const pattern of vulnData.patterns) {
|
| 793 |
+
const matches = [...code.matchAll(new RegExp(pattern.source, pattern.flags))];
|
| 794 |
+
|
| 795 |
+
matches.forEach(match => {
|
| 796 |
+
const confidence = this.calculatePatternConfidence(match, vulnData);
|
| 797 |
+
|
| 798 |
+
results.push({
|
| 799 |
+
type: vulnType,
|
| 800 |
+
confidence: confidence,
|
| 801 |
+
line: this.getLineFromMatch(code, match),
|
| 802 |
+
column: this.getColumnFromMatch(code, match),
|
| 803 |
+
match: match[0],
|
| 804 |
+
startIndex: match.index,
|
| 805 |
+
endIndex: match.index + match[0].length,
|
| 806 |
+
severity: vulnData.semantic.severity,
|
| 807 |
+
method: 'pattern_recognition'
|
| 808 |
+
});
|
| 809 |
+
});
|
| 810 |
+
}
|
| 811 |
+
}
|
| 812 |
+
|
| 813 |
+
return results;
|
| 814 |
+
}
|
| 815 |
+
|
| 816 |
+
calculatePatternConfidence(match, vulnData) {
|
| 817 |
+
let confidence = 0.7; // Base pattern confidence
|
| 818 |
+
|
| 819 |
+
// Boost confidence based on match context
|
| 820 |
+
const matchStr = match[0];
|
| 821 |
+
const contextBoost = this.getContextualBoost(matchStr, vulnData.semantic.keywords);
|
| 822 |
+
confidence += contextBoost;
|
| 823 |
+
|
| 824 |
+
return Math.min(0.99, confidence);
|
| 825 |
+
}
|
| 826 |
+
|
| 827 |
+
getContextualBoost(matchStr, keywords) {
|
| 828 |
+
let boost = 0;
|
| 829 |
+
|
| 830 |
+
// Check if match contains security keywords
|
| 831 |
+
keywords.forEach(keyword => {
|
| 832 |
+
if (matchStr.toLowerCase().includes(keyword)) {
|
| 833 |
+
boost += 0.1;
|
| 834 |
+
}
|
| 835 |
+
});
|
| 836 |
+
|
| 837 |
+
return Math.min(0.2, boost);
|
| 838 |
+
}
|
| 839 |
+
|
| 840 |
+
getLineFromMatch(code, match) {
|
| 841 |
+
const lines = code.substring(0, match.index).split('\n');
|
| 842 |
+
return lines.length;
|
| 843 |
+
}
|
| 844 |
+
|
| 845 |
+
getColumnFromMatch(code, match) {
|
| 846 |
+
const lines = code.substring(0, match.index).split('\n');
|
| 847 |
+
const lastLine = lines[lines.length - 1];
|
| 848 |
+
return lastLine.length + 1;
|
| 849 |
+
}
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
/**
|
| 853 |
+
* ML Vulnerability Classifier
|
| 854 |
+
*/
|
| 855 |
+
class MLVulnerabilityClassifier {
|
| 856 |
+
async initialize() {
|
| 857 |
+
console.log('🤖 Initializing ML Vulnerability Classifier...');
|
| 858 |
+
// Simulated ML model initialization
|
| 859 |
+
this.model = {
|
| 860 |
+
weights: new Map(),
|
| 861 |
+
bias: 0.1
|
| 862 |
+
};
|
| 863 |
+
}
|
| 864 |
+
|
| 865 |
+
async classify(code) {
|
| 866 |
+
// Simulated ML classification
|
| 867 |
+
const features = this.extractFeatures(code);
|
| 868 |
+
const prediction = this.predict(features);
|
| 869 |
+
|
| 870 |
+
return [{
|
| 871 |
+
type: prediction.threatType,
|
| 872 |
+
confidence: prediction.confidence,
|
| 873 |
+
severity: this.getSeverityScore(prediction.threatType),
|
| 874 |
+
method: 'machine_learning',
|
| 875 |
+
features: features
|
| 876 |
+
}];
|
| 877 |
+
}
|
| 878 |
+
|
| 879 |
+
extractFeatures(code) {
|
| 880 |
+
return {
|
| 881 |
+
length: code.length,
|
| 882 |
+
tokenCount: this.countTokens(code),
|
| 883 |
+
complexity: this.calculateComplexity(code),
|
| 884 |
+
suspiciousPatterns: this.countSuspiciousPatterns(code),
|
| 885 |
+
contextScore: this.calculateContextScore(code)
|
| 886 |
+
};
|
| 887 |
+
}
|
| 888 |
+
|
| 889 |
+
countTokens(code) {
|
| 890 |
+
return code
|
| 891 |
+
.replace(/[^\w]/g, ' ')
|
| 892 |
+
.split(/\s+/)
|
| 893 |
+
.filter(token => token.length > 0).length;
|
| 894 |
+
}
|
| 895 |
+
|
| 896 |
+
calculateComplexity(code) {
|
| 897 |
+
// Cyclomatic complexity approximation
|
| 898 |
+
const complexityKeywords = ['if', 'else', 'for', 'while', 'switch', 'case', 'try', 'catch'];
|
| 899 |
+
let complexity = 1;
|
| 900 |
+
|
| 901 |
+
complexityKeywords.forEach(keyword => {
|
| 902 |
+
const matches = code.match(new RegExp('\\b' + keyword + '\\b', 'g'));
|
| 903 |
+
if (matches) complexity += matches.length;
|
| 904 |
+
});
|
| 905 |
+
|
| 906 |
+
return complexity;
|
| 907 |
+
}
|
| 908 |
+
|
| 909 |
+
countSuspiciousPatterns(code) {
|
| 910 |
+
const suspicious = ['eval', 'exec', 'system', 'shell', 'cmd', 'powershell'];
|
| 911 |
+
let count = 0;
|
| 912 |
+
|
| 913 |
+
suspicious.forEach(pattern => {
|
| 914 |
+
const matches = code.match(new RegExp('\\b' + pattern + '\\b', 'gi'));
|
| 915 |
+
if (matches) count += matches.length;
|
| 916 |
+
});
|
| 917 |
+
|
| 918 |
+
return count;
|
| 919 |
+
}
|
| 920 |
+
|
| 921 |
+
calculateContextScore(code) {
|
| 922 |
+
// Score based on security-relevant context
|
| 923 |
+
let score = 0;
|
| 924 |
+
const contextPatterns = [
|
| 925 |
+
/input/i,
|
| 926 |
+
/user/i,
|
| 927 |
+
/request/i,
|
| 928 |
+
/form/i,
|
| 929 |
+
/database/i,
|
| 930 |
+
/query/i,
|
| 931 |
+
/file/i,
|
| 932 |
+
/path/i
|
| 933 |
+
];
|
| 934 |
+
|
| 935 |
+
contextPatterns.forEach(pattern => {
|
| 936 |
+
if (pattern.test(code)) score += 0.1;
|
| 937 |
+
});
|
| 938 |
+
|
| 939 |
+
return Math.min(1.0, score);
|
| 940 |
+
}
|
| 941 |
+
|
| 942 |
+
predict(features) {
|
| 943 |
+
// Simplified ML prediction
|
| 944 |
+
const threatScore = (
|
| 945 |
+
features.suspiciousPatterns * 0.3 +
|
| 946 |
+
features.complexity * 0.2 +
|
| 947 |
+
features.contextScore * 0.4 +
|
| 948 |
+
(features.length > 1000 ? 0.1 : 0)
|
| 949 |
+
);
|
| 950 |
+
|
| 951 |
+
const threatType = threatScore > 0.7 ? 'high_risk_code' :
|
| 952 |
+
threatScore > 0.4 ? 'medium_risk_code' : 'low_risk_code';
|
| 953 |
+
|
| 954 |
+
return {
|
| 955 |
+
threatType: threatType,
|
| 956 |
+
confidence: Math.min(0.95, threatScore * 1.2)
|
| 957 |
+
};
|
| 958 |
+
}
|
| 959 |
+
|
| 960 |
+
getSeverityScore(threatType) {
|
| 961 |
+
const scoreMap = {
|
| 962 |
+
'high_risk_code': 8,
|
| 963 |
+
'medium_risk_code': 5,
|
| 964 |
+
'low_risk_code': 2
|
| 965 |
+
};
|
| 966 |
+
return scoreMap[threatType] || 3;
|
| 967 |
+
}
|
| 968 |
+
}
|
| 969 |
+
|
| 970 |
+
/**
|
| 971 |
+
* Semantic Code Analyzer
|
| 972 |
+
*/
|
| 973 |
+
class SemanticCodeAnalyzer {
|
| 974 |
+
async initialize() {
|
| 975 |
+
console.log('🔬 Initializing Semantic Code Analyzer...');
|
| 976 |
+
}
|
| 977 |
+
|
| 978 |
+
async analyze(code) {
|
| 979 |
+
const results = [];
|
| 980 |
+
const semanticPatterns = this.getSemanticPatterns();
|
| 981 |
+
|
| 982 |
+
for (const [patternName, pattern] of Object.entries(semanticPatterns)) {
|
| 983 |
+
const matches = this.findSemanticMatches(code, pattern);
|
| 984 |
+
if (matches.length > 0) {
|
| 985 |
+
results.push(...matches);
|
| 986 |
+
}
|
| 987 |
+
}
|
| 988 |
+
|
| 989 |
+
return results;
|
| 990 |
+
}
|
| 991 |
+
|
| 992 |
+
getSemanticPatterns() {
|
| 993 |
+
return {
|
| 994 |
+
dangerous_function_calls: {
|
| 995 |
+
functions: ['eval', 'exec', 'system', 'shell_exec', 'passthru', 'popen'],
|
| 996 |
+
context: ['user', 'input', 'request', 'param'],
|
| 997 |
+
severity: 9
|
| 998 |
+
},
|
| 999 |
+
unsafe_file_operations: {
|
| 1000 |
+
functions: ['file_get_contents', 'fopen', 'include', 'require'],
|
| 1001 |
+
context: ['user', 'input', 'path', 'file'],
|
| 1002 |
+
severity: 8
|
| 1003 |
+
},
|
| 1004 |
+
dynamic_code_execution: {
|
| 1005 |
+
patterns: ['eval\\s*\\(', 'exec\\s*\\(', 'system\\s*\\('],
|
| 1006 |
+
context: ['variable', 'user', 'request'],
|
| 1007 |
+
severity: 10
|
| 1008 |
+
}
|
| 1009 |
+
};
|
| 1010 |
+
}
|
| 1011 |
+
|
| 1012 |
+
findSemanticMatches(code, pattern) {
|
| 1013 |
+
const results = [];
|
| 1014 |
+
|
| 1015 |
+
// Check for dangerous function calls
|
| 1016 |
+
if (pattern.functions) {
|
| 1017 |
+
pattern.functions.forEach(func => {
|
| 1018 |
+
const regex = new RegExp(`\\b${func}\\s*\\(`, 'gi');
|
| 1019 |
+
const matches = [...code.matchAll(regex)];
|
| 1020 |
+
|
| 1021 |
+
matches.forEach(match => {
|
| 1022 |
+
const context = this.extractContext(code, match.index, 50);
|
| 1023 |
+
const contextScore = this.calculateContextRelevance(context, pattern.context);
|
| 1024 |
+
|
| 1025 |
+
if (contextScore > 0.6) {
|
| 1026 |
+
results.push({
|
| 1027 |
+
type: this.getVulnerabilityType(func),
|
| 1028 |
+
confidence: contextScore,
|
| 1029 |
+
line: this.getLineNumber(code, match.index),
|
| 1030 |
+
column: this.getColumnNumber(code, match.index),
|
| 1031 |
+
match: match[0],
|
| 1032 |
+
semantic: true,
|
| 1033 |
+
severity: pattern.severity,
|
| 1034 |
+
method: 'semantic_analysis'
|
| 1035 |
+
});
|
| 1036 |
+
}
|
| 1037 |
+
});
|
| 1038 |
+
});
|
| 1039 |
+
}
|
| 1040 |
+
|
| 1041 |
+
// Check for dynamic patterns
|
| 1042 |
+
if (pattern.patterns) {
|
| 1043 |
+
pattern.patterns.forEach(pat => {
|
| 1044 |
+
const regex = new RegExp(pat, 'gi');
|
| 1045 |
+
const matches = [...code.matchAll(regex)];
|
| 1046 |
+
|
| 1047 |
+
matches.forEach(match => {
|
| 1048 |
+
const context = this.extractContext(code, match.index, 30);
|
| 1049 |
+
const contextScore = this.calculateContextRelevance(context, pattern.context);
|
| 1050 |
+
|
| 1051 |
+
if (contextScore > 0.7) {
|
| 1052 |
+
results.push({
|
| 1053 |
+
type: 'dynamic_code_execution',
|
| 1054 |
+
confidence: contextScore,
|
| 1055 |
+
line: this.getLineNumber(code, match.index),
|
| 1056 |
+
column: this.getColumnNumber(code, match.index),
|
| 1057 |
+
match: match[0],
|
| 1058 |
+
semantic: true,
|
| 1059 |
+
severity: pattern.severity,
|
| 1060 |
+
method: 'semantic_analysis'
|
| 1061 |
+
});
|
| 1062 |
+
}
|
| 1063 |
+
});
|
| 1064 |
+
});
|
| 1065 |
+
}
|
| 1066 |
+
|
| 1067 |
+
return results;
|
| 1068 |
+
}
|
| 1069 |
+
|
| 1070 |
+
extractContext(code, index, windowSize) {
|
| 1071 |
+
const start = Math.max(0, index - windowSize);
|
| 1072 |
+
const end = Math.min(code.length, index + windowSize);
|
| 1073 |
+
return code.substring(start, end);
|
| 1074 |
+
}
|
| 1075 |
+
|
| 1076 |
+
calculateContextRelevance(context, keywords) {
|
| 1077 |
+
let relevance = 0.3; // Base relevance
|
| 1078 |
+
|
| 1079 |
+
keywords.forEach(keyword => {
|
| 1080 |
+
const keywordCount = (context.match(new RegExp(keyword, 'gi')) || []).length;
|
| 1081 |
+
relevance += keywordCount * 0.2;
|
| 1082 |
+
});
|
| 1083 |
+
|
| 1084 |
+
return Math.min(0.99, relevance);
|
| 1085 |
+
}
|
| 1086 |
+
|
| 1087 |
+
getVulnerabilityType(func) {
|
| 1088 |
+
const typeMap = {
|
| 1089 |
+
'eval': 'code_injection',
|
| 1090 |
+
'exec': 'command_injection',
|
| 1091 |
+
'system': 'command_injection',
|
| 1092 |
+
'shell_exec': 'command_injection',
|
| 1093 |
+
'file_get_contents': 'file_inclusion',
|
| 1094 |
+
'fopen': 'file_inclusion',
|
| 1095 |
+
'include': 'file_inclusion',
|
| 1096 |
+
'require': 'file_inclusion'
|
| 1097 |
+
};
|
| 1098 |
+
|
| 1099 |
+
return typeMap[func] || 'unknown_function';
|
| 1100 |
+
}
|
| 1101 |
+
|
| 1102 |
+
getLineNumber(code, index) {
|
| 1103 |
+
return code.substring(0, index).split('\n').length;
|
| 1104 |
+
}
|
| 1105 |
+
|
| 1106 |
+
getColumnNumber(code, index) {
|
| 1107 |
+
const lines = code.substring(0, index).split('\n');
|
| 1108 |
+
return lines[lines.length - 1].length + 1;
|
| 1109 |
+
}
|
| 1110 |
+
}
|
| 1111 |
+
|
| 1112 |
+
/**
|
| 1113 |
+
* Contextual Analyzer
|
| 1114 |
+
*/
|
| 1115 |
+
class ContextualAnalyzer {
|
| 1116 |
+
async initialize() {
|
| 1117 |
+
console.log('🔍 Initializing Contextual Analyzer...');
|
| 1118 |
+
}
|
| 1119 |
+
|
| 1120 |
+
async analyze(code) {
|
| 1121 |
+
const results = [];
|
| 1122 |
+
|
| 1123 |
+
// Analyze code structure and context
|
| 1124 |
+
const context = this.analyzeCodeContext(code);
|
| 1125 |
+
const dataFlow = this.analyzeDataFlow(code);
|
| 1126 |
+
const controlFlow = this.analyzeControlFlow(code);
|
| 1127 |
+
|
| 1128 |
+
// Check for contextual vulnerabilities
|
| 1129 |
+
if (context.hasUserInput) {
|
| 1130 |
+
results.push(...this.checkInputValidation(code));
|
| 1131 |
+
}
|
| 1132 |
+
|
| 1133 |
+
if (context.hasDatabaseOperations) {
|
| 1134 |
+
results.push(...this.checkDatabaseSecurity(code));
|
| 1135 |
+
}
|
| 1136 |
+
|
| 1137 |
+
if (context.hasFileOperations) {
|
| 1138 |
+
results.push(...this.checkFileSecurity(code));
|
| 1139 |
+
}
|
| 1140 |
+
|
| 1141 |
+
if (context.hasNetworkOperations) {
|
| 1142 |
+
results.push(...this.checkNetworkSecurity(code));
|
| 1143 |
+
}
|
| 1144 |
+
|
| 1145 |
+
return results;
|
| 1146 |
+
}
|
| 1147 |
+
|
| 1148 |
+
analyzeCodeContext(code) {
|
| 1149 |
+
return {
|
| 1150 |
+
hasUserInput: /input|request|get|post|param/i.test(code),
|
| 1151 |
+
hasDatabaseOperations: /database|query|select|insert|update|delete/i.test(code),
|
| 1152 |
+
hasFileOperations: /file|read|write|open|include|require/i.test(code),
|
| 1153 |
+
hasNetworkOperations: /http|https|curl|fetch|ajax/i.test(code),
|
| 1154 |
+
hasDynamicContent: /eval|exec|system|shell/i.test(code),
|
| 1155 |
+
complexity: this.calculateCodeComplexity(code)
|
| 1156 |
+
};
|
| 1157 |
+
}
|
| 1158 |
+
|
| 1159 |
+
calculateCodeComplexity(code) {
|
| 1160 |
+
let complexity = 0;
|
| 1161 |
+
const complexityIndicators = [
|
| 1162 |
+
/if\s*\(/g, /else/g, /for\s*\(/g, /while\s*\(/g,
|
| 1163 |
+
/switch/g, /case/g, /try/g, /catch/g, /\?\s*[^:]+:/g
|
| 1164 |
+
];
|
| 1165 |
+
|
| 1166 |
+
complexityIndicators.forEach(pattern => {
|
| 1167 |
+
const matches = code.match(pattern);
|
| 1168 |
+
if (matches) complexity += matches.length;
|
| 1169 |
+
});
|
| 1170 |
+
|
| 1171 |
+
return complexity;
|
| 1172 |
+
}
|
| 1173 |
+
|
| 1174 |
+
analyzeDataFlow(code) {
|
| 1175 |
+
// Simplified data flow analysis
|
| 1176 |
+
return {
|
| 1177 |
+
sources: this.identifyDataSources(code),
|
| 1178 |
+
sinks: this.identifyDataSinks(code),
|
| 1179 |
+
transformations: this.identifyTransformations(code)
|
| 1180 |
+
};
|
| 1181 |
+
}
|
| 1182 |
+
|
| 1183 |
+
identifyDataSources(code) {
|
| 1184 |
+
const sources = [];
|
| 1185 |
+
const sourcePatterns = [
|
| 1186 |
+
/\$_(?:GET|POST|REQUEST|COOKIE|SERVER)\[/g,
|
| 1187 |
+
/input\s*\(/g,
|
| 1188 |
+
/prompt\s*\(/g,
|
| 1189 |
+
/readline\s*\(/g
|
| 1190 |
+
];
|
| 1191 |
+
|
| 1192 |
+
sourcePatterns.forEach(pattern => {
|
| 1193 |
+
const matches = code.match(pattern);
|
| 1194 |
+
if (matches) sources.push(...matches);
|
| 1195 |
+
});
|
| 1196 |
+
|
| 1197 |
+
return sources;
|
| 1198 |
+
}
|
| 1199 |
+
|
| 1200 |
+
identifyDataSinks(code) {
|
| 1201 |
+
const sinks = [];
|
| 1202 |
+
const sinkPatterns = [
|
| 1203 |
+
/innerHTML\s*=/g,
|
| 1204 |
+
/document\.write\s*\(/g,
|
| 1205 |
+
/eval\s*\(/g,
|
| 1206 |
+
/exec\s*\(/g,
|
| 1207 |
+
/system\s*\(/g,
|
| 1208 |
+
/file_put_contents\s*\(/g
|
| 1209 |
+
];
|
| 1210 |
+
|
| 1211 |
+
sinkPatterns.forEach(pattern => {
|
| 1212 |
+
const matches = code.match(pattern);
|
| 1213 |
+
if (matches) sinks.push(...matches);
|
| 1214 |
+
});
|
| 1215 |
+
|
| 1216 |
+
return sinks;
|
| 1217 |
+
}
|
| 1218 |
+
|
| 1219 |
+
identifyTransformations(code) {
|
| 1220 |
+
const transformations = [];
|
| 1221 |
+
const transformPatterns = [
|
| 1222 |
+
/htmlspecialchars\s*\(/g,
|
| 1223 |
+
/addslashes\s*\(/g,
|
| 1224 |
+
/mysql_real_escape_string\s*\(/g,
|
| 1225 |
+
/json_encode\s*\(/g,
|
| 1226 |
+
/base64_encode\s*\(/g
|
| 1227 |
+
];
|
| 1228 |
+
|
| 1229 |
+
transformPatterns.forEach(pattern => {
|
| 1230 |
+
const matches = code.match(pattern);
|
| 1231 |
+
if (matches) transformations.push(...matches);
|
| 1232 |
+
});
|
| 1233 |
+
|
| 1234 |
+
return transformations;
|
| 1235 |
+
}
|
| 1236 |
+
|
| 1237 |
+
analyzeControlFlow(code) {
|
| 1238 |
+
// Simplified control flow analysis
|
| 1239 |
+
return {
|
| 1240 |
+
hasConditionals: /if\s*\(/.test(code),
|
| 1241 |
+
hasLoops: /for\s*\(/.test(code) || /while\s*\(/.test(code),
|
| 1242 |
+
hasExceptions: /try\s*\{/.test(code),
|
| 1243 |
+
depth: this.calculateNestingDepth(code)
|
| 1244 |
+
};
|
| 1245 |
+
}
|
| 1246 |
+
|
| 1247 |
+
calculateNestingDepth(code) {
|
| 1248 |
+
let maxDepth = 0;
|
| 1249 |
+
let currentDepth = 0;
|
| 1250 |
+
|
| 1251 |
+
for (const char of code) {
|
| 1252 |
+
if (char === '{') {
|
| 1253 |
+
currentDepth++;
|
| 1254 |
+
maxDepth = Math.max(maxDepth, currentDepth);
|
| 1255 |
+
} else if (char === '}') {
|
| 1256 |
+
currentDepth--;
|
| 1257 |
+
}
|
| 1258 |
+
}
|
| 1259 |
+
|
| 1260 |
+
return maxDepth;
|
| 1261 |
+
}
|
| 1262 |
+
|
| 1263 |
+
checkInputValidation(code) {
|
| 1264 |
+
const results = [];
|
| 1265 |
+
|
| 1266 |
+
// Check if user input is used without validation
|
| 1267 |
+
if (/\$_(?:GET|POST|REQUEST)/.test(code) && !/filter_var|htmlspecialchars|addslashes/.test(code)) {
|
| 1268 |
+
results.push({
|
| 1269 |
+
type: 'missing_input_validation',
|
| 1270 |
+
confidence: 0.8,
|
| 1271 |
+
severity: 7,
|
| 1272 |
+
method: 'contextual_analysis',
|
| 1273 |
+
message: 'User input used without proper validation'
|
| 1274 |
+
});
|
| 1275 |
+
}
|
| 1276 |
+
|
| 1277 |
+
return results;
|
| 1278 |
+
}
|
| 1279 |
+
|
| 1280 |
+
checkDatabaseSecurity(code) {
|
| 1281 |
+
const results = [];
|
| 1282 |
+
|
| 1283 |
+
// Check for SQL injection patterns
|
| 1284 |
+
if (/\$_(?:GET|POST|REQUEST)/.test(code) && /query|select|insert|update|delete/i.test(code)) {
|
| 1285 |
+
if (!/prepare|parameterized|bind_param/.test(code)) {
|
| 1286 |
+
results.push({
|
| 1287 |
+
type: 'potential_sql_injection',
|
| 1288 |
+
confidence: 0.7,
|
| 1289 |
+
severity: 9,
|
| 1290 |
+
method: 'contextual_analysis',
|
| 1291 |
+
message: 'Potential SQL injection vulnerability detected'
|
| 1292 |
+
});
|
| 1293 |
+
}
|
| 1294 |
+
}
|
| 1295 |
+
|
| 1296 |
+
return results;
|
| 1297 |
+
}
|
| 1298 |
+
|
| 1299 |
+
checkFileSecurity(code) {
|
| 1300 |
+
const results = [];
|
| 1301 |
+
|
| 1302 |
+
// Check for file inclusion with user input
|
| 1303 |
+
if (/\$_(?:GET|POST|REQUEST)/.test(code) && /(include|require)(_once)?\s*\(/i.test(code)) {
|
| 1304 |
+
results.push({
|
| 1305 |
+
type: 'file_inclusion_vulnerability',
|
| 1306 |
+
confidence: 0.8,
|
| 1307 |
+
severity: 8,
|
| 1308 |
+
method: 'contextual_analysis',
|
| 1309 |
+
message: 'File inclusion with user input detected'
|
| 1310 |
+
});
|
| 1311 |
+
}
|
| 1312 |
+
|
| 1313 |
+
return results;
|
| 1314 |
+
}
|
| 1315 |
+
|
| 1316 |
+
checkNetworkSecurity(code) {
|
| 1317 |
+
const results = [];
|
| 1318 |
+
|
| 1319 |
+
// Check for insecure HTTP requests
|
| 1320 |
+
if (/http:\/\//.test(code) && !/https:\/\//.test(code)) {
|
| 1321 |
+
results.push({
|
| 1322 |
+
type: 'insecure_http_request',
|
| 1323 |
+
confidence: 0.9,
|
| 1324 |
+
severity: 6,
|
| 1325 |
+
method: 'contextual_analysis',
|
| 1326 |
+
message: 'Insecure HTTP request detected (should use HTTPS)'
|
| 1327 |
+
});
|
| 1328 |
+
}
|
| 1329 |
+
|
| 1330 |
+
return results;
|
| 1331 |
+
}
|
| 1332 |
+
}
|
| 1333 |
+
|
| 1334 |
+
// Export for use in other modules
|
| 1335 |
+
if (typeof module !== 'undefined' && module.exports) {
|
| 1336 |
+
module.exports = {
|
| 1337 |
+
AdvancedVulnerabilityDetector,
|
| 1338 |
+
NLPVulnerabilityEngine,
|
| 1339 |
+
AdvancedPatternRecognizer,
|
| 1340 |
+
MLVulnerabilityClassifier,
|
| 1341 |
+
SemanticCodeAnalyzer,
|
| 1342 |
+
ContextualAnalyzer
|
| 1343 |
+
};
|
| 1344 |
+
}
|
js/ai-behavioral-analyzer.js
ADDED
|
@@ -0,0 +1,734 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* AI Behavioral Analysis System
|
| 3 |
+
* Advanced threat detection using behavioral patterns and machine learning
|
| 4 |
+
* Author: MiniMax Agent
|
| 5 |
+
* Date: 2025-12-10
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
class AIBehavioralAnalyzer {
|
| 9 |
+
constructor() {
|
| 10 |
+
this.behavioralModels = new Map();
|
| 11 |
+
this.anomalyDetector = new AnomalyDetector();
|
| 12 |
+
this.patternLearner = new PatternLearner();
|
| 13 |
+
this.threatClassifier = new ThreatClassifier();
|
| 14 |
+
this.behavioralBaseline = new Map();
|
| 15 |
+
this.sessionData = [];
|
| 16 |
+
this.mlModel = null;
|
| 17 |
+
this.initialized = false;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
async initialize() {
|
| 21 |
+
try {
|
| 22 |
+
console.log('🤖 Initializing AI Behavioral Analyzer...');
|
| 23 |
+
|
| 24 |
+
// Initialize behavioral models
|
| 25 |
+
await this.loadBehavioralModels();
|
| 26 |
+
|
| 27 |
+
// Setup ML model for pattern recognition
|
| 28 |
+
await this.initializeMLModel();
|
| 29 |
+
|
| 30 |
+
// Create behavioral baselines
|
| 31 |
+
this.createBehavioralBaselines();
|
| 32 |
+
|
| 33 |
+
// Start real-time monitoring
|
| 34 |
+
this.startBehavioralMonitoring();
|
| 35 |
+
|
| 36 |
+
this.initialized = true;
|
| 37 |
+
console.log('✅ AI Behavioral Analyzer initialized successfully');
|
| 38 |
+
|
| 39 |
+
} catch (error) {
|
| 40 |
+
console.error('❌ Failed to initialize AI Behavioral Analyzer:', error);
|
| 41 |
+
throw error;
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
async loadBehavioralModels() {
|
| 46 |
+
// Define behavioral patterns for different threat types
|
| 47 |
+
this.behavioralModels.set('xss', {
|
| 48 |
+
patterns: [
|
| 49 |
+
{ action: 'rapid_input_changes', weight: 0.8 },
|
| 50 |
+
{ action: 'unusual_event_timing', weight: 0.7 },
|
| 51 |
+
{ action: 'suspicious_character_patterns', weight: 0.9 }
|
| 52 |
+
],
|
| 53 |
+
thresholds: {
|
| 54 |
+
inputRate: 50, // inputs per minute
|
| 55 |
+
scriptDetection: true,
|
| 56 |
+
domManipulation: 'high'
|
| 57 |
+
}
|
| 58 |
+
});
|
| 59 |
+
|
| 60 |
+
this.behavioralModels.set('sql_injection', {
|
| 61 |
+
patterns: [
|
| 62 |
+
{ action: 'sql_keyword_frequency', weight: 0.9 },
|
| 63 |
+
{ action: 'query_complexity_spike', weight: 0.8 },
|
| 64 |
+
{ action: 'error_message_patterns', weight: 0.7 }
|
| 65 |
+
],
|
| 66 |
+
thresholds: {
|
| 67 |
+
sqlKeywordRate: 10, // SQL keywords per minute
|
| 68 |
+
queryComplexity: 0.8,
|
| 69 |
+
errorRate: 0.3
|
| 70 |
+
}
|
| 71 |
+
});
|
| 72 |
+
|
| 73 |
+
this.behavioralModels.set('csrf', {
|
| 74 |
+
patterns: [
|
| 75 |
+
{ action: 'cross_domain_requests', weight: 0.8 },
|
| 76 |
+
{ action: 'form_submission_patterns', weight: 0.9 },
|
| 77 |
+
{ action: 'session_token_misuse', weight: 0.9 }
|
| 78 |
+
],
|
| 79 |
+
thresholds: {
|
| 80 |
+
crossDomainRequests: 5,
|
| 81 |
+
formSubmissionRate: 20,
|
| 82 |
+
tokenValidation: false
|
| 83 |
+
}
|
| 84 |
+
});
|
| 85 |
+
|
| 86 |
+
this.behavioralModels.set('clickjacking', {
|
| 87 |
+
patterns: [
|
| 88 |
+
{ action: 'iframe_embedding', weight: 0.9 },
|
| 89 |
+
{ action: 'overlay_manipulation', weight: 0.8 },
|
| 90 |
+
{ action: 'cursor_position_anomalies', weight: 0.7 }
|
| 91 |
+
],
|
| 92 |
+
thresholds: {
|
| 93 |
+
iframeDetection: true,
|
| 94 |
+
overlayComplexity: 0.7,
|
| 95 |
+
cursorJitter: 0.5
|
| 96 |
+
}
|
| 97 |
+
});
|
| 98 |
+
|
| 99 |
+
this.behavioralModels.set('advanced_persistent_threat', {
|
| 100 |
+
patterns: [
|
| 101 |
+
{ action: 'long_term_surveillance', weight: 0.9 },
|
| 102 |
+
{ action: 'stealth_data_exfiltration', weight: 0.95 },
|
| 103 |
+
{ action: 'lateral_movement_patterns', weight: 0.9 }
|
| 104 |
+
],
|
| 105 |
+
thresholds: {
|
| 106 |
+
sessionDuration: 3600000, // 1 hour
|
| 107 |
+
dataTransferRate: 1000000, // 1MB/s
|
| 108 |
+
networkConnections: 50
|
| 109 |
+
}
|
| 110 |
+
});
|
| 111 |
+
}
|
| 112 |
+
|
| 113 |
+
async initializeMLModel() {
|
| 114 |
+
// Simulate machine learning model initialization
|
| 115 |
+
// In production, this would load actual TensorFlow.js or similar models
|
| 116 |
+
|
| 117 |
+
this.mlModel = {
|
| 118 |
+
predictThreat: (features) => {
|
| 119 |
+
// Simulated ML prediction with confidence scoring
|
| 120 |
+
const threatScore = Math.random();
|
| 121 |
+
const confidence = 0.7 + Math.random() * 0.3;
|
| 122 |
+
|
| 123 |
+
return {
|
| 124 |
+
threatScore,
|
| 125 |
+
confidence,
|
| 126 |
+
prediction: threatScore > 0.7 ? 'malicious' : 'benign',
|
| 127 |
+
features
|
| 128 |
+
};
|
| 129 |
+
},
|
| 130 |
+
|
| 131 |
+
updateModel: (newData) => {
|
| 132 |
+
// Simulated model updates
|
| 133 |
+
console.log('🧠 ML Model updated with new behavioral data');
|
| 134 |
+
return true;
|
| 135 |
+
}
|
| 136 |
+
};
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
createBehavioralBaselines() {
|
| 140 |
+
// Create baseline profiles for normal user behavior
|
| 141 |
+
this.behavioralBaseline.set('normal_user', {
|
| 142 |
+
clickRate: { min: 2, max: 8 }, // clicks per second
|
| 143 |
+
typingSpeed: { min: 120, max: 300 }, // WPM
|
| 144 |
+
scrollPattern: 'smooth',
|
| 145 |
+
navigationTime: { min: 1000, max: 30000 }, // ms
|
| 146 |
+
formInteraction: 'deliberate',
|
| 147 |
+
errorRate: { min: 0, max: 0.1 } // 0-10%
|
| 148 |
+
});
|
| 149 |
+
|
| 150 |
+
this.behavioralBaseline.set('bot_behavior', {
|
| 151 |
+
clickRate: { min: 10, max: 100 },
|
| 152 |
+
typingSpeed: 0, // No typing
|
| 153 |
+
scrollPattern: 'linear',
|
| 154 |
+
navigationTime: { min: 100, max: 1000 },
|
| 155 |
+
formInteraction: 'rapid',
|
| 156 |
+
errorRate: { min: 0, max: 0.05 }
|
| 157 |
+
});
|
| 158 |
+
|
| 159 |
+
this.behavioralBaseline.set('automated_tool', {
|
| 160 |
+
clickRate: { min: 50, max: 500 },
|
| 161 |
+
typingSpeed: 0,
|
| 162 |
+
scrollPattern: 'instant',
|
| 163 |
+
navigationTime: { min: 10, max: 100 },
|
| 164 |
+
formInteraction: 'instant',
|
| 165 |
+
errorRate: { min: 0, max: 0.02 }
|
| 166 |
+
});
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
startBehavioralMonitoring() {
|
| 170 |
+
// Monitor various behavioral indicators
|
| 171 |
+
this.setupEventListeners();
|
| 172 |
+
this.startPerformanceMonitoring();
|
| 173 |
+
this.startNetworkMonitoring();
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
setupEventListeners() {
|
| 177 |
+
// Mouse behavior monitoring
|
| 178 |
+
let mouseEvents = [];
|
| 179 |
+
let lastMouseMove = Date.now();
|
| 180 |
+
|
| 181 |
+
document.addEventListener('mousemove', (e) => {
|
| 182 |
+
const now = Date.now();
|
| 183 |
+
const timeDiff = now - lastMouseMove;
|
| 184 |
+
lastMouseMove = now;
|
| 185 |
+
|
| 186 |
+
mouseEvents.push({
|
| 187 |
+
timestamp: now,
|
| 188 |
+
x: e.clientX,
|
| 189 |
+
y: e.clientY,
|
| 190 |
+
timeDiff: timeDiff
|
| 191 |
+
});
|
| 192 |
+
|
| 193 |
+
// Keep only recent events (last 10 seconds)
|
| 194 |
+
mouseEvents = mouseEvents.filter(event => now - event.timestamp < 10000);
|
| 195 |
+
|
| 196 |
+
// Analyze mouse behavior patterns
|
| 197 |
+
this.analyzeMouseBehavior(mouseEvents);
|
| 198 |
+
});
|
| 199 |
+
|
| 200 |
+
// Keyboard behavior monitoring
|
| 201 |
+
let keystrokes = [];
|
| 202 |
+
document.addEventListener('keydown', (e) => {
|
| 203 |
+
keystrokes.push({
|
| 204 |
+
timestamp: Date.now(),
|
| 205 |
+
key: e.key,
|
| 206 |
+
code: e.code,
|
| 207 |
+
altKey: e.altKey,
|
| 208 |
+
ctrlKey: e.ctrlKey,
|
| 209 |
+
shiftKey: e.shiftKey
|
| 210 |
+
});
|
| 211 |
+
|
| 212 |
+
this.analyzeKeyboardBehavior(keystrokes);
|
| 213 |
+
});
|
| 214 |
+
|
| 215 |
+
// Form interaction monitoring
|
| 216 |
+
document.addEventListener('input', (e) => {
|
| 217 |
+
this.analyzeInputBehavior(e);
|
| 218 |
+
});
|
| 219 |
+
|
| 220 |
+
// Navigation patterns
|
| 221 |
+
document.addEventListener('click', (e) => {
|
| 222 |
+
this.analyzeClickBehavior(e);
|
| 223 |
+
});
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
analyzeMouseBehavior(events) {
|
| 227 |
+
if (events.length < 5) return;
|
| 228 |
+
|
| 229 |
+
const now = Date.now();
|
| 230 |
+
const recentEvents = events.filter(e => now - e.timestamp < 5000);
|
| 231 |
+
|
| 232 |
+
// Calculate movement patterns
|
| 233 |
+
const speeds = [];
|
| 234 |
+
for (let i = 1; i < recentEvents.length; i++) {
|
| 235 |
+
const dx = recentEvents[i].x - recentEvents[i-1].x;
|
| 236 |
+
const dy = recentEvents[i].y - recentEvents[i-1].y;
|
| 237 |
+
const distance = Math.sqrt(dx*dx + dy*dy);
|
| 238 |
+
const timeDiff = recentEvents[i].timeDiff;
|
| 239 |
+
const speed = timeDiff > 0 ? distance / timeDiff : 0;
|
| 240 |
+
speeds.push(speed);
|
| 241 |
+
}
|
| 242 |
+
|
| 243 |
+
const avgSpeed = speeds.reduce((a, b) => a + b, 0) / speeds.length;
|
| 244 |
+
const speedVariance = speeds.reduce((sum, speed) => sum + Math.pow(speed - avgSpeed, 2), 0) / speeds.length;
|
| 245 |
+
|
| 246 |
+
// Detect bot-like behavior
|
| 247 |
+
if (avgSpeed > 50 || speedVariance < 10) {
|
| 248 |
+
this.reportAnomaly('mouse_behavior', {
|
| 249 |
+
type: 'suspicious_mouse_pattern',
|
| 250 |
+
speed: avgSpeed,
|
| 251 |
+
variance: speedVariance,
|
| 252 |
+
confidence: Math.min(0.9, (avgSpeed / 100) + (10 / (speedVariance + 1)))
|
| 253 |
+
});
|
| 254 |
+
}
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
analyzeKeyboardBehavior(keystrokes) {
|
| 258 |
+
const now = Date.now();
|
| 259 |
+
const recentKeystrokes = keystrokes.filter(k => now - k.timestamp < 60000);
|
| 260 |
+
|
| 261 |
+
if (recentKeystrokes.length < 10) return;
|
| 262 |
+
|
| 263 |
+
// Calculate typing patterns
|
| 264 |
+
const intervals = [];
|
| 265 |
+
for (let i = 1; i < recentKeystrokes.length; i++) {
|
| 266 |
+
intervals.push(recentKeystrokes[i].timestamp - recentKeystrokes[i-1].timestamp);
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
const avgInterval = intervals.reduce((a, b) => a + b, 0) / intervals.length;
|
| 270 |
+
const intervalVariance = intervals.reduce((sum, interval) => sum + Math.pow(interval - avgInterval, 2), 0) / intervals.length;
|
| 271 |
+
|
| 272 |
+
// Detect automated typing
|
| 273 |
+
if (avgInterval < 50 && intervalVariance < 100) {
|
| 274 |
+
this.reportAnomaly('keyboard_behavior', {
|
| 275 |
+
type: 'automated_typing',
|
| 276 |
+
avgInterval: avgInterval,
|
| 277 |
+
variance: intervalVariance,
|
| 278 |
+
confidence: Math.min(0.9, (100 - avgInterval) / 100)
|
| 279 |
+
});
|
| 280 |
+
}
|
| 281 |
+
}
|
| 282 |
+
|
| 283 |
+
analyzeInputBehavior(inputEvent) {
|
| 284 |
+
const input = inputEvent.target;
|
| 285 |
+
const value = input.value;
|
| 286 |
+
const now = Date.now();
|
| 287 |
+
|
| 288 |
+
// Detect suspicious input patterns
|
| 289 |
+
const suspiciousPatterns = [
|
| 290 |
+
/<script/i,
|
| 291 |
+
/javascript:/i,
|
| 292 |
+
/eval\s*\(/i,
|
| 293 |
+
/document\./i,
|
| 294 |
+
/window\./i,
|
| 295 |
+
/on\w+\s*=/i,
|
| 296 |
+
/union\s+select/i,
|
| 297 |
+
/drop\s+table/i,
|
| 298 |
+
/admin'--/i,
|
| 299 |
+
/'or'1'='1/i
|
| 300 |
+
];
|
| 301 |
+
|
| 302 |
+
for (const pattern of suspiciousPatterns) {
|
| 303 |
+
if (pattern.test(value)) {
|
| 304 |
+
this.reportAnomaly('input_behavior', {
|
| 305 |
+
type: 'suspicious_input_pattern',
|
| 306 |
+
pattern: pattern.source,
|
| 307 |
+
element: input.tagName,
|
| 308 |
+
confidence: 0.95
|
| 309 |
+
});
|
| 310 |
+
break;
|
| 311 |
+
}
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
// Monitor input rate
|
| 315 |
+
if (!this.inputRateTracker) {
|
| 316 |
+
this.inputRateTracker = { count: 0, startTime: now };
|
| 317 |
+
}
|
| 318 |
+
|
| 319 |
+
this.inputRateTracker.count++;
|
| 320 |
+
if (now - this.inputRateTracker.startTime > 60000) {
|
| 321 |
+
if (this.inputRateTracker.count > 100) {
|
| 322 |
+
this.reportAnomaly('input_behavior', {
|
| 323 |
+
type: 'high_input_rate',
|
| 324 |
+
rate: this.inputRateTracker.count,
|
| 325 |
+
confidence: Math.min(0.8, this.inputRateTracker.count / 200)
|
| 326 |
+
});
|
| 327 |
+
}
|
| 328 |
+
this.inputRateTracker = { count: 0, startTime: now };
|
| 329 |
+
}
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
analyzeClickBehavior(clickEvent) {
|
| 333 |
+
const element = clickEvent.target;
|
| 334 |
+
const now = Date.now();
|
| 335 |
+
|
| 336 |
+
if (!this.clickTracker) {
|
| 337 |
+
this.clickTracker = [];
|
| 338 |
+
}
|
| 339 |
+
|
| 340 |
+
this.clickTracker.push({
|
| 341 |
+
timestamp: now,
|
| 342 |
+
element: element.tagName,
|
| 343 |
+
text: element.textContent?.substring(0, 50) || '',
|
| 344 |
+
position: { x: clickEvent.clientX, y: clickEvent.clientY }
|
| 345 |
+
});
|
| 346 |
+
|
| 347 |
+
// Keep only recent clicks (last 10 seconds)
|
| 348 |
+
this.clickTracker = this.clickTracker.filter(click => now - click.timestamp < 10000);
|
| 349 |
+
|
| 350 |
+
// Detect rapid clicking
|
| 351 |
+
if (this.clickTracker.length > 20) {
|
| 352 |
+
this.reportAnomaly('click_behavior', {
|
| 353 |
+
type: 'rapid_clicking',
|
| 354 |
+
clickCount: this.clickTracker.length,
|
| 355 |
+
confidence: Math.min(0.8, this.clickTracker.length / 50)
|
| 356 |
+
});
|
| 357 |
+
}
|
| 358 |
+
|
| 359 |
+
// Detect suspicious element targeting
|
| 360 |
+
if (element.tagName === 'FORM' || element.getAttribute('type') === 'submit') {
|
| 361 |
+
this.reportAnomaly('click_behavior', {
|
| 362 |
+
type: 'form_targeting',
|
| 363 |
+
element: element.outerHTML.substring(0, 200),
|
| 364 |
+
confidence: 0.6
|
| 365 |
+
});
|
| 366 |
+
}
|
| 367 |
+
}
|
| 368 |
+
|
| 369 |
+
startPerformanceMonitoring() {
|
| 370 |
+
// Monitor performance metrics that might indicate attacks
|
| 371 |
+
setInterval(() => {
|
| 372 |
+
const perfData = performance.getEntriesByType('navigation')[0];
|
| 373 |
+
if (perfData) {
|
| 374 |
+
this.analyzePerformanceMetrics(perfData);
|
| 375 |
+
}
|
| 376 |
+
}, 5000);
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
analyzePerformanceMetrics(perfData) {
|
| 380 |
+
// Detect unusual performance patterns
|
| 381 |
+
if (perfData.loadEventEnd - perfData.loadEventStart > 10000) {
|
| 382 |
+
this.reportAnomaly('performance', {
|
| 383 |
+
type: 'slow_page_load',
|
| 384 |
+
loadTime: perfData.loadEventEnd - perfData.loadEventStart,
|
| 385 |
+
confidence: 0.7
|
| 386 |
+
});
|
| 387 |
+
}
|
| 388 |
+
|
| 389 |
+
// Monitor memory usage
|
| 390 |
+
if (performance.memory) {
|
| 391 |
+
const memoryUsage = performance.memory.usedJSHeapSize;
|
| 392 |
+
if (memoryUsage > 100 * 1024 * 1024) { // 100MB
|
| 393 |
+
this.reportAnomaly('performance', {
|
| 394 |
+
type: 'high_memory_usage',
|
| 395 |
+
usage: memoryUsage,
|
| 396 |
+
confidence: 0.6
|
| 397 |
+
});
|
| 398 |
+
}
|
| 399 |
+
}
|
| 400 |
+
}
|
| 401 |
+
|
| 402 |
+
startNetworkMonitoring() {
|
| 403 |
+
// Monitor network requests for suspicious patterns
|
| 404 |
+
const originalFetch = window.fetch;
|
| 405 |
+
window.fetch = async (...args) => {
|
| 406 |
+
const response = await originalFetch(...args);
|
| 407 |
+
this.analyzeNetworkRequest(args[0], response);
|
| 408 |
+
return response;
|
| 409 |
+
};
|
| 410 |
+
}
|
| 411 |
+
|
| 412 |
+
analyzeNetworkRequest(url, response) {
|
| 413 |
+
// Detect suspicious network patterns
|
| 414 |
+
const suspiciousPatterns = [
|
| 415 |
+
/\/admin/i,
|
| 416 |
+
/\/api\/.*\b(select|drop|insert|update|delete)\b/i,
|
| 417 |
+
/\/upload/i,
|
| 418 |
+
/\/exec/i,
|
| 419 |
+
/\/system/i
|
| 420 |
+
];
|
| 421 |
+
|
| 422 |
+
for (const pattern of suspiciousPatterns) {
|
| 423 |
+
if (pattern.test(url)) {
|
| 424 |
+
this.reportAnomaly('network', {
|
| 425 |
+
type: 'suspicious_request',
|
| 426 |
+
url: url,
|
| 427 |
+
pattern: pattern.source,
|
| 428 |
+
confidence: 0.8
|
| 429 |
+
});
|
| 430 |
+
}
|
| 431 |
+
}
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
reportAnomaly(category, anomaly) {
|
| 435 |
+
const report = {
|
| 436 |
+
timestamp: Date.now(),
|
| 437 |
+
category: category,
|
| 438 |
+
anomaly: anomaly,
|
| 439 |
+
sessionId: this.getSessionId(),
|
| 440 |
+
userAgent: navigator.userAgent,
|
| 441 |
+
url: window.location.href
|
| 442 |
+
};
|
| 443 |
+
|
| 444 |
+
// Store anomaly report
|
| 445 |
+
if (!this.anomalies) this.anomalies = [];
|
| 446 |
+
this.anomalies.push(report);
|
| 447 |
+
|
| 448 |
+
// Trigger immediate analysis if critical
|
| 449 |
+
if (anomaly.confidence > 0.8) {
|
| 450 |
+
this.performThreatAssessment(report);
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
console.warn('🚨 Behavioral Anomaly Detected:', report);
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
async performThreatAssessment(anomalyReport) {
|
| 457 |
+
try {
|
| 458 |
+
// Combine multiple anomaly reports for comprehensive analysis
|
| 459 |
+
const recentAnomalies = this.getRecentAnomalies(300000); // Last 5 minutes
|
| 460 |
+
|
| 461 |
+
// Use ML model for threat classification
|
| 462 |
+
const features = this.extractFeatures(recentAnomalies);
|
| 463 |
+
const prediction = await this.mlModel.predictThreat(features);
|
| 464 |
+
|
| 465 |
+
// Classify threat type and severity
|
| 466 |
+
const threatAssessment = await this.threatClassifier.classify(
|
| 467 |
+
recentAnomalies,
|
| 468 |
+
prediction
|
| 469 |
+
);
|
| 470 |
+
|
| 471 |
+
// Generate response recommendations
|
| 472 |
+
const response = this.generateResponseRecommendations(threatAssessment);
|
| 473 |
+
|
| 474 |
+
// Trigger automated response if needed
|
| 475 |
+
if (threatAssessment.severity > 0.8) {
|
| 476 |
+
await this.triggerAutomatedResponse(threatAssessment);
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
return {
|
| 480 |
+
anomalyReport,
|
| 481 |
+
threatAssessment,
|
| 482 |
+
prediction,
|
| 483 |
+
response,
|
| 484 |
+
timestamp: Date.now()
|
| 485 |
+
};
|
| 486 |
+
|
| 487 |
+
} catch (error) {
|
| 488 |
+
console.error('Threat assessment failed:', error);
|
| 489 |
+
}
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
getRecentAnomalies(timeWindow) {
|
| 493 |
+
const now = Date.now();
|
| 494 |
+
return (this.anomalies || []).filter(
|
| 495 |
+
anomaly => now - anomaly.timestamp < timeWindow
|
| 496 |
+
);
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
extractFeatures(anomalies) {
|
| 500 |
+
return {
|
| 501 |
+
anomalyCount: anomalies.length,
|
| 502 |
+
categories: [...new Set(anomalies.map(a => a.category))],
|
| 503 |
+
avgConfidence: anomalies.reduce((sum, a) => sum + a.anomaly.confidence, 0) / anomalies.length,
|
| 504 |
+
timeDistribution: this.calculateTimeDistribution(anomalies),
|
| 505 |
+
severityScore: this.calculateSeverityScore(anomalies)
|
| 506 |
+
};
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
calculateTimeDistribution(anomalies) {
|
| 510 |
+
const intervals = [];
|
| 511 |
+
for (let i = 1; i < anomalies.length; i++) {
|
| 512 |
+
intervals.push(anomalies[i].timestamp - anomalies[i-1].timestamp);
|
| 513 |
+
}
|
| 514 |
+
return {
|
| 515 |
+
avgInterval: intervals.reduce((a, b) => a + b, 0) / intervals.length,
|
| 516 |
+
variance: this.calculateVariance(intervals)
|
| 517 |
+
};
|
| 518 |
+
}
|
| 519 |
+
|
| 520 |
+
calculateVariance(values) {
|
| 521 |
+
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
| 522 |
+
return values.reduce((sum, value) => sum + Math.pow(value - mean, 2), 0) / values.length;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
calculateSeverityScore(anomalies) {
|
| 526 |
+
return anomalies.reduce((score, anomaly) => {
|
| 527 |
+
return score + (anomaly.anomaly.confidence * 10);
|
| 528 |
+
}, 0);
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
generateResponseRecommendations(threatAssessment) {
|
| 532 |
+
const recommendations = [];
|
| 533 |
+
|
| 534 |
+
switch (threatAssessment.threatType) {
|
| 535 |
+
case 'xss_attempt':
|
| 536 |
+
recommendations.push({
|
| 537 |
+
action: 'Enable strict CSP',
|
| 538 |
+
priority: 'high',
|
| 539 |
+
implementation: "Content-Security-Policy: default-src 'none'; script-src 'self';"
|
| 540 |
+
});
|
| 541 |
+
break;
|
| 542 |
+
|
| 543 |
+
case 'sql_injection':
|
| 544 |
+
recommendations.push({
|
| 545 |
+
action: 'Implement input validation',
|
| 546 |
+
priority: 'critical',
|
| 547 |
+
implementation: 'Use parameterized queries and sanitized inputs'
|
| 548 |
+
});
|
| 549 |
+
break;
|
| 550 |
+
|
| 551 |
+
case 'bot_activity':
|
| 552 |
+
recommendations.push({
|
| 553 |
+
action: 'Implement rate limiting',
|
| 554 |
+
priority: 'medium',
|
| 555 |
+
implementation: 'Limit requests to 10 per minute per IP'
|
| 556 |
+
});
|
| 557 |
+
break;
|
| 558 |
+
|
| 559 |
+
case 'advanced_persistent_threat':
|
| 560 |
+
recommendations.push({
|
| 561 |
+
action: 'Enhanced monitoring',
|
| 562 |
+
priority: 'critical',
|
| 563 |
+
implementation: 'Activate comprehensive logging and alert system'
|
| 564 |
+
});
|
| 565 |
+
break;
|
| 566 |
+
}
|
| 567 |
+
|
| 568 |
+
return recommendations;
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
async triggerAutomatedResponse(threatAssessment) {
|
| 572 |
+
console.log('🚨 Triggering automated response for:', threatAssessment.threatType);
|
| 573 |
+
|
| 574 |
+
// Implement automated response actions
|
| 575 |
+
switch (threatAssessment.threatType) {
|
| 576 |
+
case 'bot_activity':
|
| 577 |
+
this.enableRateLimiting();
|
| 578 |
+
break;
|
| 579 |
+
|
| 580 |
+
case 'sql_injection':
|
| 581 |
+
this.temporaryBlockSuspiciousRequests();
|
| 582 |
+
break;
|
| 583 |
+
|
| 584 |
+
case 'xss_attempt':
|
| 585 |
+
this.enhanceCSP();
|
| 586 |
+
break;
|
| 587 |
+
}
|
| 588 |
+
}
|
| 589 |
+
|
| 590 |
+
enableRateLimiting() {
|
| 591 |
+
// Implement rate limiting
|
| 592 |
+
console.log('⚡ Rate limiting activated');
|
| 593 |
+
}
|
| 594 |
+
|
| 595 |
+
temporaryBlockSuspiciousRequests() {
|
| 596 |
+
// Block suspicious requests temporarily
|
| 597 |
+
console.log('🛡️ Suspicious request blocking activated');
|
| 598 |
+
}
|
| 599 |
+
|
| 600 |
+
enhanceCSP() {
|
| 601 |
+
// Enhance Content Security Policy
|
| 602 |
+
console.log('🔒 Enhanced CSP activated');
|
| 603 |
+
}
|
| 604 |
+
|
| 605 |
+
getSessionId() {
|
| 606 |
+
if (!this.sessionId) {
|
| 607 |
+
this.sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
| 608 |
+
}
|
| 609 |
+
return this.sessionId;
|
| 610 |
+
}
|
| 611 |
+
|
| 612 |
+
// Public API for external threat analysis
|
| 613 |
+
async analyzeThreatContext(context) {
|
| 614 |
+
if (!this.initialized) {
|
| 615 |
+
await this.initialize();
|
| 616 |
+
}
|
| 617 |
+
|
| 618 |
+
return await this.performThreatAssessment({
|
| 619 |
+
timestamp: Date.now(),
|
| 620 |
+
category: 'manual_analysis',
|
| 621 |
+
anomaly: {
|
| 622 |
+
type: 'manual_context_analysis',
|
| 623 |
+
context: context,
|
| 624 |
+
confidence: 0.9
|
| 625 |
+
},
|
| 626 |
+
sessionId: this.getSessionId()
|
| 627 |
+
});
|
| 628 |
+
}
|
| 629 |
+
|
| 630 |
+
// Export behavioral data for analysis
|
| 631 |
+
exportBehavioralData() {
|
| 632 |
+
return {
|
| 633 |
+
sessionId: this.sessionId,
|
| 634 |
+
anomalies: this.anomalies || [],
|
| 635 |
+
sessionData: this.sessionData,
|
| 636 |
+
behavioralBaseline: Object.fromEntries(this.behavioralBaseline),
|
| 637 |
+
timestamp: Date.now()
|
| 638 |
+
};
|
| 639 |
+
}
|
| 640 |
+
}
|
| 641 |
+
|
| 642 |
+
/**
|
| 643 |
+
* Anomaly Detection Engine
|
| 644 |
+
*/
|
| 645 |
+
class AnomalyDetector {
|
| 646 |
+
constructor() {
|
| 647 |
+
this.threshold = 0.7;
|
| 648 |
+
this.learningRate = 0.1;
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
detectAnomaly(data, baseline) {
|
| 652 |
+
// Statistical anomaly detection
|
| 653 |
+
const deviation = this.calculateDeviation(data, baseline);
|
| 654 |
+
return {
|
| 655 |
+
isAnomaly: deviation > this.threshold,
|
| 656 |
+
deviation: deviation,
|
| 657 |
+
confidence: Math.min(0.95, deviation)
|
| 658 |
+
};
|
| 659 |
+
}
|
| 660 |
+
|
| 661 |
+
calculateDeviation(data, baseline) {
|
| 662 |
+
// Calculate statistical deviation from baseline
|
| 663 |
+
return Math.abs(data - baseline) / (baseline + 0.001);
|
| 664 |
+
}
|
| 665 |
+
}
|
| 666 |
+
|
| 667 |
+
/**
|
| 668 |
+
* Pattern Learning System
|
| 669 |
+
*/
|
| 670 |
+
class PatternLearner {
|
| 671 |
+
constructor() {
|
| 672 |
+
this.patterns = new Map();
|
| 673 |
+
this.learningData = [];
|
| 674 |
+
}
|
| 675 |
+
|
| 676 |
+
learnFromData(data) {
|
| 677 |
+
this.learningData.push(data);
|
| 678 |
+
this.updatePatterns();
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
updatePatterns() {
|
| 682 |
+
// Update learned patterns based on new data
|
| 683 |
+
if (this.learningData.length > 100) {
|
| 684 |
+
console.log('🧠 Updating learned patterns...');
|
| 685 |
+
// Implementation would update ML model here
|
| 686 |
+
}
|
| 687 |
+
}
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
/**
|
| 691 |
+
* Threat Classification System
|
| 692 |
+
*/
|
| 693 |
+
class ThreatClassifier {
|
| 694 |
+
async classify(anomalies, prediction) {
|
| 695 |
+
// Classify threat type based on anomaly patterns
|
| 696 |
+
const threatTypes = this.identifyThreatTypes(anomalies);
|
| 697 |
+
const severity = this.calculateSeverity(anomalies, prediction);
|
| 698 |
+
|
| 699 |
+
return {
|
| 700 |
+
threatType: threatTypes[0] || 'unknown',
|
| 701 |
+
threatTypes: threatTypes,
|
| 702 |
+
severity: severity,
|
| 703 |
+
confidence: prediction.confidence,
|
| 704 |
+
classificationTime: Date.now()
|
| 705 |
+
};
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
identifyThreatTypes(anomalies) {
|
| 709 |
+
const types = [];
|
| 710 |
+
|
| 711 |
+
const categoryCounts = anomalies.reduce((counts, anomaly) => {
|
| 712 |
+
counts[anomaly.category] = (counts[anomaly.category] || 0) + 1;
|
| 713 |
+
return counts;
|
| 714 |
+
}, {});
|
| 715 |
+
|
| 716 |
+
// Map categories to threat types
|
| 717 |
+
if (categoryCounts.input_behavior > 3) types.push('xss_attempt');
|
| 718 |
+
if (categoryCounts.network > 2) types.push('injection_attempt');
|
| 719 |
+
if (categoryCounts.click_behavior > 10) types.push('bot_activity');
|
| 720 |
+
if (categoryCounts.performance > 5) types.push('dos_attempt');
|
| 721 |
+
|
| 722 |
+
return types;
|
| 723 |
+
}
|
| 724 |
+
|
| 725 |
+
calculateSeverity(anomalies, prediction) {
|
| 726 |
+
const avgConfidence = anomalies.reduce((sum, a) => sum + a.anomaly.confidence, 0) / anomalies.length;
|
| 727 |
+
return Math.max(avgConfidence, prediction.threatScore);
|
| 728 |
+
}
|
| 729 |
+
}
|
| 730 |
+
|
| 731 |
+
// Export for use in other modules
|
| 732 |
+
if (typeof module !== 'undefined' && module.exports) {
|
| 733 |
+
module.exports = { AIBehavioralAnalyzer, AnomalyDetector, PatternLearner, ThreatClassifier };
|
| 734 |
+
}
|
js/ai-threat-analyzer.js
ADDED
|
@@ -0,0 +1,694 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* محلل التهديدات بالذكاء الاصطناعي
|
| 3 |
+
* AI-Powered Threat Analyzer
|
| 4 |
+
* Real-time threat detection and analysis system
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
class AIThreatAnalyzer {
|
| 8 |
+
constructor() {
|
| 9 |
+
this.threatPatterns = {
|
| 10 |
+
xss: [
|
| 11 |
+
/<script[^>]*>[\s\S]*?<\/script>/gi,
|
| 12 |
+
/javascript:/gi,
|
| 13 |
+
/on\w+\s*=/gi,
|
| 14 |
+
/<iframe[^>]*>/gi,
|
| 15 |
+
/<object[^>]*>/gi,
|
| 16 |
+
/<embed[^>]*>/gi
|
| 17 |
+
],
|
| 18 |
+
injection: [
|
| 19 |
+
/union\s+select/gi,
|
| 20 |
+
/drop\s+table/gi,
|
| 21 |
+
/insert\s+into/gi,
|
| 22 |
+
/delete\s+from/gi,
|
| 23 |
+
/--/gi,
|
| 24 |
+
/;/gi,
|
| 25 |
+
/\|/gi,
|
| 26 |
+
/\bOR\b\s+1=1/gi,
|
| 27 |
+
/\bAND\b\s+1=1/gi
|
| 28 |
+
],
|
| 29 |
+
csrf: [
|
| 30 |
+
/<form[^>]*method\s*=\s*["']?post["']?[^>]*>/gi,
|
| 31 |
+
/<input[^>]*name\s*=\s*["']?_token["']?[^>]*>/gi,
|
| 32 |
+
/<meta[^>]*name\s*=\s*["']?csrf-token["']?[^>]*>/gi
|
| 33 |
+
],
|
| 34 |
+
clickjacking: [
|
| 35 |
+
/<iframe[^>]*src\s*=\s*["']?https?:\/\//gi,
|
| 36 |
+
/style\s*=\s*["']?position\s*:\s*absolute/gi,
|
| 37 |
+
/z-index\s*:\s*\d+/gi
|
| 38 |
+
]
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
this.severityLevels = {
|
| 42 |
+
critical: { score: 90, color: '#FF4444', label: 'حرج' },
|
| 43 |
+
high: { score: 70, color: '#FF8800', label: 'عالي' },
|
| 44 |
+
medium: { score: 40, color: '#FFAA00', label: 'متوسط' },
|
| 45 |
+
low: { score: 20, color: '#FFDD00', label: 'منخفض' },
|
| 46 |
+
info: { score: 10, color: '#44AA44', label: 'معلوماتي' }
|
| 47 |
+
};
|
| 48 |
+
|
| 49 |
+
this.analysisHistory = [];
|
| 50 |
+
this.isAnalyzing = false;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
/**
|
| 54 |
+
* تحليل شامل للتهديدات في المحتوى
|
| 55 |
+
* Comprehensive threat analysis in content
|
| 56 |
+
*/
|
| 57 |
+
analyzeContent(content, source = 'unknown') {
|
| 58 |
+
if (this.isAnalyzing) {
|
| 59 |
+
return Promise.reject(new Error('تحليل正在进行中...'));
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
this.isAnalyzing = true;
|
| 63 |
+
|
| 64 |
+
const analysisResult = {
|
| 65 |
+
timestamp: new Date().toISOString(),
|
| 66 |
+
source: source,
|
| 67 |
+
threats: [],
|
| 68 |
+
riskScore: 0,
|
| 69 |
+
recommendations: [],
|
| 70 |
+
details: {}
|
| 71 |
+
};
|
| 72 |
+
|
| 73 |
+
try {
|
| 74 |
+
// تحليل أنماط XSS
|
| 75 |
+
analysisResult.details.xss = this.analyzeXSS(content);
|
| 76 |
+
|
| 77 |
+
// تحليل أنماط SQL Injection
|
| 78 |
+
analysisResult.details.injection = this.analyzeInjection(content);
|
| 79 |
+
|
| 80 |
+
// تحليل أنماط CSRF
|
| 81 |
+
analysisResult.details.csrf = this.analyzeCSRF(content);
|
| 82 |
+
|
| 83 |
+
// تحليل أنماط Clickjacking
|
| 84 |
+
analysisResult.details.clickjacking = this.analyzeClickjacking(content);
|
| 85 |
+
|
| 86 |
+
// تحليل المحتوى المشبوه
|
| 87 |
+
analysisResult.details.suspicious = this.analyzeSuspiciousContent(content);
|
| 88 |
+
|
| 89 |
+
// حساب درجة المخاطر الإجمالية
|
| 90 |
+
analysisResult.riskScore = this.calculateOverallRisk(analysisResult.details);
|
| 91 |
+
|
| 92 |
+
// تحديد التهديدات الرئيسية
|
| 93 |
+
analysisResult.threats = this.identifyTopThreats(analysisResult.details);
|
| 94 |
+
|
| 95 |
+
// توليد التوصيات
|
| 96 |
+
analysisResult.recommendations = this.generateRecommendations(analysisResult.details);
|
| 97 |
+
|
| 98 |
+
// حفظ في السجل
|
| 99 |
+
this.analysisHistory.push(analysisResult);
|
| 100 |
+
|
| 101 |
+
// الحفاظ على آخر 100 تحليل فقط
|
| 102 |
+
if (this.analysisHistory.length > 100) {
|
| 103 |
+
this.analysisHistory.shift();
|
| 104 |
+
}
|
| 105 |
+
|
| 106 |
+
return Promise.resolve(analysisResult);
|
| 107 |
+
|
| 108 |
+
} catch (error) {
|
| 109 |
+
console.error('خطأ في تحليل التهديدات:', error);
|
| 110 |
+
return Promise.reject(error);
|
| 111 |
+
} finally {
|
| 112 |
+
this.isAnalyzing = false;
|
| 113 |
+
}
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
/**
|
| 117 |
+
* تحليل أنماط XSS
|
| 118 |
+
* XSS pattern analysis
|
| 119 |
+
*/
|
| 120 |
+
analyzeXSS(content) {
|
| 121 |
+
const xssFindings = [];
|
| 122 |
+
let riskScore = 0;
|
| 123 |
+
|
| 124 |
+
this.threatPatterns.xss.forEach((pattern, index) => {
|
| 125 |
+
const matches = content.match(pattern);
|
| 126 |
+
if (matches) {
|
| 127 |
+
matches.forEach(match => {
|
| 128 |
+
xssFindings.push({
|
| 129 |
+
type: 'XSS',
|
| 130 |
+
pattern: pattern.toString(),
|
| 131 |
+
match: match.substring(0, 100),
|
| 132 |
+
severity: this.getSeverityByPattern('xss', index),
|
| 133 |
+
line: this.findLineNumber(content, match)
|
| 134 |
+
});
|
| 135 |
+
riskScore += this.getSeverityScore('xss', index);
|
| 136 |
+
});
|
| 137 |
+
}
|
| 138 |
+
});
|
| 139 |
+
|
| 140 |
+
return {
|
| 141 |
+
findings: xssFindings,
|
| 142 |
+
riskScore: Math.min(riskScore, 100),
|
| 143 |
+
level: this.getRiskLevel(riskScore)
|
| 144 |
+
};
|
| 145 |
+
}
|
| 146 |
+
|
| 147 |
+
/**
|
| 148 |
+
* تحليل أنماط Injection
|
| 149 |
+
* Injection pattern analysis
|
| 150 |
+
*/
|
| 151 |
+
analyzeInjection(content) {
|
| 152 |
+
const injectionFindings = [];
|
| 153 |
+
let riskScore = 0;
|
| 154 |
+
|
| 155 |
+
this.threatPatterns.injection.forEach((pattern, index) => {
|
| 156 |
+
const matches = content.match(pattern);
|
| 157 |
+
if (matches) {
|
| 158 |
+
matches.forEach(match => {
|
| 159 |
+
injectionFindings.push({
|
| 160 |
+
type: 'Injection',
|
| 161 |
+
pattern: pattern.toString(),
|
| 162 |
+
match: match.substring(0, 100),
|
| 163 |
+
severity: this.getSeverityByPattern('injection', index),
|
| 164 |
+
line: this.findLineNumber(content, match)
|
| 165 |
+
});
|
| 166 |
+
riskScore += this.getSeverityScore('injection', index);
|
| 167 |
+
});
|
| 168 |
+
}
|
| 169 |
+
});
|
| 170 |
+
|
| 171 |
+
return {
|
| 172 |
+
findings: injectionFindings,
|
| 173 |
+
riskScore: Math.min(riskScore, 100),
|
| 174 |
+
level: this.getRiskLevel(riskScore)
|
| 175 |
+
};
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
/**
|
| 179 |
+
* تحليل أنماط CSRF
|
| 180 |
+
* CSRF pattern analysis
|
| 181 |
+
*/
|
| 182 |
+
analyzeCSRF(content) {
|
| 183 |
+
const csrfFindings = [];
|
| 184 |
+
let riskScore = 0;
|
| 185 |
+
|
| 186 |
+
this.threatPatterns.csrf.forEach((pattern, index) => {
|
| 187 |
+
const matches = content.match(pattern);
|
| 188 |
+
if (matches) {
|
| 189 |
+
matches.forEach(match => {
|
| 190 |
+
csrfFindings.push({
|
| 191 |
+
type: 'CSRF',
|
| 192 |
+
pattern: pattern.toString(),
|
| 193 |
+
match: match.substring(0, 100),
|
| 194 |
+
severity: this.getSeverityByPattern('csrf', index),
|
| 195 |
+
line: this.findLineNumber(content, match)
|
| 196 |
+
});
|
| 197 |
+
riskScore += this.getSeverityScore('csrf', index);
|
| 198 |
+
});
|
| 199 |
+
}
|
| 200 |
+
});
|
| 201 |
+
|
| 202 |
+
return {
|
| 203 |
+
findings: csrfFindings,
|
| 204 |
+
riskScore: Math.min(riskScore, 100),
|
| 205 |
+
level: this.getRiskLevel(riskScore)
|
| 206 |
+
};
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
/**
|
| 210 |
+
* تحليل أنماط Clickjacking
|
| 211 |
+
* Clickjacking pattern analysis
|
| 212 |
+
*/
|
| 213 |
+
analyzeClickjacking(content) {
|
| 214 |
+
const clickjackingFindings = [];
|
| 215 |
+
let riskScore = 0;
|
| 216 |
+
|
| 217 |
+
this.threatPatterns.clickjacking.forEach((pattern, index) => {
|
| 218 |
+
const matches = content.match(pattern);
|
| 219 |
+
if (matches) {
|
| 220 |
+
matches.forEach(match => {
|
| 221 |
+
clickjackingFindings.push({
|
| 222 |
+
type: 'Clickjacking',
|
| 223 |
+
pattern: pattern.toString(),
|
| 224 |
+
match: match.substring(0, 100),
|
| 225 |
+
severity: this.getSeverityByPattern('clickjacking', index),
|
| 226 |
+
line: this.findLineNumber(content, match)
|
| 227 |
+
});
|
| 228 |
+
riskScore += this.getSeverityScore('clickjacking', index);
|
| 229 |
+
});
|
| 230 |
+
}
|
| 231 |
+
});
|
| 232 |
+
|
| 233 |
+
return {
|
| 234 |
+
findings: clickjackingFindings,
|
| 235 |
+
riskScore: Math.min(riskScore, 100),
|
| 236 |
+
level: this.getRiskLevel(riskScore)
|
| 237 |
+
};
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
/**
|
| 241 |
+
* تحليل المحتوى المشبوه العام
|
| 242 |
+
* General suspicious content analysis
|
| 243 |
+
*/
|
| 244 |
+
analyzeSuspiciousContent(content) {
|
| 245 |
+
const suspiciousFindings = [];
|
| 246 |
+
const suspiciousPatterns = [
|
| 247 |
+
{ pattern: /eval\s*\(/gi, severity: 'critical', description: 'استخدام eval() خطير' },
|
| 248 |
+
{ pattern: /innerHTML\s*=/gi, severity: 'high', description: 'استخدام innerHTML قد يؤدي لـ XSS' },
|
| 249 |
+
{ pattern: /document\.write/gi, severity: 'high', description: 'document.write يمكن أن يكون خطيراً' },
|
| 250 |
+
{ pattern: /localStorage\s*\./gi, severity: 'medium', description: 'استخدام localStorage يحتاج مراجعة' },
|
| 251 |
+
{ pattern: /sessionStorage\s*\./gi, severity: 'medium', description: 'استخدام sessionStorage يحتاج مراجعة' },
|
| 252 |
+
{ pattern: /fetch\s*\(/gi, severity: 'low', description: 'اتصال شبكي يحتاج مراجعة' },
|
| 253 |
+
{ pattern: /XMLHttpRequest/gi, severity: 'low', description: 'اتصال شبكي قد يحتاج مراجعة' }
|
| 254 |
+
];
|
| 255 |
+
|
| 256 |
+
suspiciousPatterns.forEach(({ pattern, severity, description }) => {
|
| 257 |
+
const matches = content.match(pattern);
|
| 258 |
+
if (matches) {
|
| 259 |
+
matches.forEach(match => {
|
| 260 |
+
suspiciousFindings.push({
|
| 261 |
+
type: 'Suspicious',
|
| 262 |
+
pattern: pattern.toString(),
|
| 263 |
+
match: match.substring(0, 100),
|
| 264 |
+
severity: severity,
|
| 265 |
+
description: description,
|
| 266 |
+
line: this.findLineNumber(content, match)
|
| 267 |
+
});
|
| 268 |
+
});
|
| 269 |
+
}
|
| 270 |
+
});
|
| 271 |
+
|
| 272 |
+
return {
|
| 273 |
+
findings: suspiciousFindings,
|
| 274 |
+
totalFindings: suspiciousFindings.length
|
| 275 |
+
};
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
/**
|
| 279 |
+
* حساب درجة المخاطر الإجمالية
|
| 280 |
+
* Calculate overall risk score
|
| 281 |
+
*/
|
| 282 |
+
calculateOverallRisk(details) {
|
| 283 |
+
const weights = {
|
| 284 |
+
xss: 0.3,
|
| 285 |
+
injection: 0.25,
|
| 286 |
+
csrf: 0.2,
|
| 287 |
+
clickjacking: 0.15,
|
| 288 |
+
suspicious: 0.1
|
| 289 |
+
};
|
| 290 |
+
|
| 291 |
+
let totalScore = 0;
|
| 292 |
+
|
| 293 |
+
if (details.xss) totalScore += details.xss.riskScore * weights.xss;
|
| 294 |
+
if (details.injection) totalScore += details.injection.riskScore * weights.injection;
|
| 295 |
+
if (details.csrf) totalScore += details.csrf.riskScore * weights.csrf;
|
| 296 |
+
if (details.clickjacking) totalScore += details.clickjacking.riskScore * weights.clickjacking;
|
| 297 |
+
if (details.suspicious) totalScore += Math.min(details.suspicious.totalFindings * 10, 50) * weights.suspicious;
|
| 298 |
+
|
| 299 |
+
return Math.round(Math.min(totalScore, 100));
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
/**
|
| 303 |
+
* تحديد التهديدات الرئيسية
|
| 304 |
+
* Identify top threats
|
| 305 |
+
*/
|
| 306 |
+
identifyTopThreats(details) {
|
| 307 |
+
const threats = [];
|
| 308 |
+
|
| 309 |
+
Object.keys(details).forEach(category => {
|
| 310 |
+
if (details[category] && details[category].findings) {
|
| 311 |
+
details[category].findings.forEach(finding => {
|
| 312 |
+
threats.push({
|
| 313 |
+
...finding,
|
| 314 |
+
category: category,
|
| 315 |
+
impact: this.calculateImpact(finding),
|
| 316 |
+
likelihood: this.calculateLikelihood(finding)
|
| 317 |
+
});
|
| 318 |
+
});
|
| 319 |
+
}
|
| 320 |
+
});
|
| 321 |
+
|
| 322 |
+
// ترتيب التهديدات حسب الخطورة
|
| 323 |
+
return threats.sort((a, b) => {
|
| 324 |
+
const severityOrder = { critical: 4, high: 3, medium: 2, low: 1, info: 0 };
|
| 325 |
+
return severityOrder[b.severity] - severityOrder[a.severity];
|
| 326 |
+
}).slice(0, 10); // أفضل 10 تهديدات
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
/**
|
| 330 |
+
* توليد التوصيات
|
| 331 |
+
* Generate recommendations
|
| 332 |
+
*/
|
| 333 |
+
generateRecommendations(details) {
|
| 334 |
+
const recommendations = [];
|
| 335 |
+
|
| 336 |
+
// توصيات XSS
|
| 337 |
+
if (details.xss && details.xss.riskScore > 0) {
|
| 338 |
+
recommendations.push({
|
| 339 |
+
priority: 'عالية',
|
| 340 |
+
category: 'XSS',
|
| 341 |
+
title: 'حماية من هجمات Cross-Site Scripting',
|
| 342 |
+
description: 'استخدم CSP مع strict-dynamic وrequire-trusted-types-for',
|
| 343 |
+
implementation: this.generateCSPRecommendations(details.xss.findings),
|
| 344 |
+
severity: details.xss.level
|
| 345 |
+
});
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
+
// توصيات Injection
|
| 349 |
+
if (details.injection && details.injection.riskScore > 0) {
|
| 350 |
+
recommendations.push({
|
| 351 |
+
priority: 'عالية',
|
| 352 |
+
category: 'Injection',
|
| 353 |
+
title: 'حماية من هجمات SQL Injection',
|
| 354 |
+
description: 'استخدم parameterized queries وinput validation',
|
| 355 |
+
implementation: this.generateInjectionRecommendations(details.injection.findings),
|
| 356 |
+
severity: details.injection.level
|
| 357 |
+
});
|
| 358 |
+
}
|
| 359 |
+
|
| 360 |
+
// توصيات CSRF
|
| 361 |
+
if (details.csrf && details.csrf.riskScore > 0) {
|
| 362 |
+
recommendations.push({
|
| 363 |
+
priority: 'متوسطة',
|
| 364 |
+
category: 'CSRF',
|
| 365 |
+
title: 'حماية من هجمات Cross-Site Request Forgery',
|
| 366 |
+
description: 'استخدم CSRF tokens وSameSite cookies',
|
| 367 |
+
implementation: this.generateCSRFRecommendations(details.csrf.findings),
|
| 368 |
+
severity: details.csrf.level
|
| 369 |
+
});
|
| 370 |
+
}
|
| 371 |
+
|
| 372 |
+
// توصيات عامة
|
| 373 |
+
if (details.suspicious && details.suspicious.totalFindings > 5) {
|
| 374 |
+
recommendations.push({
|
| 375 |
+
priority: 'متوسطة',
|
| 376 |
+
category: 'General',
|
| 377 |
+
title: 'مراجعة الكود العام',
|
| 378 |
+
description: 'قم بمراجعة الكود للتأكد من اتباع أفضل الممارسات الأمنية',
|
| 379 |
+
implementation: this.generateGeneralRecommendations(details.suspicious.findings),
|
| 380 |
+
severity: 'medium'
|
| 381 |
+
});
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
return recommendations;
|
| 385 |
+
}
|
| 386 |
+
|
| 387 |
+
/**
|
| 388 |
+
* توليد توصيات CSP
|
| 389 |
+
* Generate CSP recommendations
|
| 390 |
+
*/
|
| 391 |
+
generateCSPRecommendations(xssFindings) {
|
| 392 |
+
const hasInline = xssFindings.some(f => f.match.includes('<script'));
|
| 393 |
+
const hasExternal = xssFindings.some(f => f.match.includes('src='));
|
| 394 |
+
|
| 395 |
+
let csp = "default-src 'self';";
|
| 396 |
+
|
| 397 |
+
if (hasExternal) {
|
| 398 |
+
csp += " script-src 'self' 'unsafe-inline';";
|
| 399 |
+
} else {
|
| 400 |
+
csp += " script-src 'self' 'unsafe-eval' 'unsafe-inline';";
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
csp += " style-src 'self' 'unsafe-inline';";
|
| 404 |
+
csp += " img-src 'self' data: https:;";
|
| 405 |
+
csp += " font-src 'self';";
|
| 406 |
+
csp += " connect-src 'self';";
|
| 407 |
+
csp += " frame-ancestors 'none';";
|
| 408 |
+
csp += " base-uri 'self';";
|
| 409 |
+
csp += " form-action 'self';";
|
| 410 |
+
|
| 411 |
+
return [
|
| 412 |
+
`أضف رأس HTTP التالي: Content-Security-Policy: ${csp}`,
|
| 413 |
+
'استخدم Trusted Types API للحماية من DOM XSS',
|
| 414 |
+
'تجنب استخدام innerHTML وdocument.write',
|
| 415 |
+
'استخدم textContent بدلاً من innerHTML',
|
| 416 |
+
'قم بتشفير جميع المدخلات من المستخدمين'
|
| 417 |
+
];
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
/**
|
| 421 |
+
* توليد توصيات Injection
|
| 422 |
+
* Generate injection recommendations
|
| 423 |
+
*/
|
| 424 |
+
generateInjectionRecommendations(injectionFindings) {
|
| 425 |
+
return [
|
| 426 |
+
'استخدم parameterized queries لجميع استعلامات قاعدة البيانات',
|
| 427 |
+
'قم بتطبيق input validation صارم',
|
| 428 |
+
'استخدم ORM آمن مثل Prisma أو TypeORM',
|
| 429 |
+
'قم بتطبيق principle of least privilege',
|
| 430 |
+
'استخدم prepared statements في جميع الاستعلامات'
|
| 431 |
+
];
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
/**
|
| 435 |
+
* توليد توصيات CSRF
|
| 436 |
+
* Generate CSRF recommendations
|
| 437 |
+
*/
|
| 438 |
+
generateCSRFRecommendations(csrfFindings) {
|
| 439 |
+
return [
|
| 440 |
+
'أضف CSRF tokens لجميع النماذج',
|
| 441 |
+
'استخدم SameSite cookies',
|
| 442 |
+
'تطبيق referer validation',
|
| 443 |
+
'استخدم double submit cookie pattern',
|
| 444 |
+
'استخدم SameSite=Strict للcookies الحساسة'
|
| 445 |
+
];
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
/**
|
| 449 |
+
* توليد توصيات عامة
|
| 450 |
+
* Generate general recommendations
|
| 451 |
+
*/
|
| 452 |
+
generateGeneralRecommendations(suspiciousFindings) {
|
| 453 |
+
const commonIssues = suspiciousFindings.map(f => f.description);
|
| 454 |
+
const uniqueIssues = [...new Set(commonIssues)];
|
| 455 |
+
|
| 456 |
+
return uniqueIssues.map(issue => `مراجعة: ${issue}`).concat([
|
| 457 |
+
'تطبيق code review process',
|
| 458 |
+
'استخدام static code analysis tools',
|
| 459 |
+
'تطبيق security testing في CI/CD',
|
| 460 |
+
'تحديث جميع المكتبات بانتظام'
|
| 461 |
+
]);
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
/**
|
| 465 |
+
* حساب التأثير
|
| 466 |
+
* Calculate impact
|
| 467 |
+
*/
|
| 468 |
+
calculateImpact(finding) {
|
| 469 |
+
const impactScores = {
|
| 470 |
+
critical: 9,
|
| 471 |
+
high: 7,
|
| 472 |
+
medium: 5,
|
| 473 |
+
low: 3,
|
| 474 |
+
info: 1
|
| 475 |
+
};
|
| 476 |
+
return impactScores[finding.severity] || 1;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
/**
|
| 480 |
+
* حساب الاحتمالية
|
| 481 |
+
* Calculate likelihood
|
| 482 |
+
*/
|
| 483 |
+
calculateLikelihood(finding) {
|
| 484 |
+
// حساب مبسط للاحتمالية بناءً على نوع التهديد
|
| 485 |
+
const likelihoodScores = {
|
| 486 |
+
xss: 8,
|
| 487 |
+
injection: 7,
|
| 488 |
+
csrf: 6,
|
| 489 |
+
clickjacking: 5,
|
| 490 |
+
suspicious: 4
|
| 491 |
+
};
|
| 492 |
+
return likelihoodScores[finding.type.toLowerCase()] || 3;
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
/**
|
| 496 |
+
* الحصول على درجة الخطورة حسب النمط
|
| 497 |
+
* Get severity by pattern
|
| 498 |
+
*/
|
| 499 |
+
getSeverityByPattern(category, patternIndex) {
|
| 500 |
+
const severities = {
|
| 501 |
+
xss: ['critical', 'high', 'high', 'medium', 'medium'],
|
| 502 |
+
injection: ['critical', 'critical', 'high', 'high', 'medium', 'medium', 'medium', 'medium', 'medium'],
|
| 503 |
+
csrf: ['high', 'medium', 'medium'],
|
| 504 |
+
clickjacking: ['medium', 'low', 'low']
|
| 505 |
+
};
|
| 506 |
+
return severities[category]?.[patternIndex] || 'low';
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
/**
|
| 510 |
+
* الحصول على درجة الخطورة
|
| 511 |
+
* Get severity score
|
| 512 |
+
*/
|
| 513 |
+
getSeverityScore(category, patternIndex) {
|
| 514 |
+
const severity = this.getSeverityByPattern(category, patternIndex);
|
| 515 |
+
const scores = {
|
| 516 |
+
critical: 25,
|
| 517 |
+
high: 15,
|
| 518 |
+
medium: 10,
|
| 519 |
+
low: 5,
|
| 520 |
+
info: 2
|
| 521 |
+
};
|
| 522 |
+
return scores[severity] || 2;
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
/**
|
| 526 |
+
* الحصول على مستوى المخاطر
|
| 527 |
+
* Get risk level
|
| 528 |
+
*/
|
| 529 |
+
getRiskLevel(score) {
|
| 530 |
+
if (score >= 80) return 'critical';
|
| 531 |
+
if (score >= 60) return 'high';
|
| 532 |
+
if (score >= 40) return 'medium';
|
| 533 |
+
if (score >= 20) return 'low';
|
| 534 |
+
return 'info';
|
| 535 |
+
}
|
| 536 |
+
|
| 537 |
+
/**
|
| 538 |
+
* العثور على رقم السطر
|
| 539 |
+
* Find line number
|
| 540 |
+
*/
|
| 541 |
+
findLineNumber(content, match) {
|
| 542 |
+
const lines = content.substring(0, content.indexOf(match)).split('\n');
|
| 543 |
+
return lines.length;
|
| 544 |
+
}
|
| 545 |
+
|
| 546 |
+
/**
|
| 547 |
+
* الحصول على سجل التحليل
|
| 548 |
+
* Get analysis history
|
| 549 |
+
*/
|
| 550 |
+
getAnalysisHistory(limit = 10) {
|
| 551 |
+
return this.analysisHistory.slice(-limit).reverse();
|
| 552 |
+
}
|
| 553 |
+
|
| 554 |
+
/**
|
| 555 |
+
* تصدير التقرير
|
| 556 |
+
* Export report
|
| 557 |
+
*/
|
| 558 |
+
exportReport(analysisResult, format = 'json') {
|
| 559 |
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
| 560 |
+
const filename = `threat-analysis-${timestamp}.${format}`;
|
| 561 |
+
|
| 562 |
+
if (format === 'json') {
|
| 563 |
+
const dataStr = JSON.stringify(analysisResult, null, 2);
|
| 564 |
+
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
| 565 |
+
const url = URL.createObjectURL(dataBlob);
|
| 566 |
+
|
| 567 |
+
const link = document.createElement('a');
|
| 568 |
+
link.href = url;
|
| 569 |
+
link.download = filename;
|
| 570 |
+
link.click();
|
| 571 |
+
|
| 572 |
+
URL.revokeObjectURL(url);
|
| 573 |
+
} else if (format === 'html') {
|
| 574 |
+
const html = this.generateHTMLReport(analysisResult);
|
| 575 |
+
const dataBlob = new Blob([html], { type: 'text/html' });
|
| 576 |
+
const url = URL.createObjectURL(dataBlob);
|
| 577 |
+
|
| 578 |
+
const link = document.createElement('a');
|
| 579 |
+
link.href = url;
|
| 580 |
+
link.download = filename;
|
| 581 |
+
link.click();
|
| 582 |
+
|
| 583 |
+
URL.revokeObjectURL(url);
|
| 584 |
+
}
|
| 585 |
+
}
|
| 586 |
+
|
| 587 |
+
/**
|
| 588 |
+
* توليد تقرير HTML
|
| 589 |
+
* Generate HTML report
|
| 590 |
+
*/
|
| 591 |
+
generateHTMLReport(analysisResult) {
|
| 592 |
+
return `
|
| 593 |
+
<!DOCTYPE html>
|
| 594 |
+
<html dir="rtl" lang="ar">
|
| 595 |
+
<head>
|
| 596 |
+
<meta charset="UTF-8">
|
| 597 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 598 |
+
<title>تقرير تحليل التهديدات - Threat Analysis Report</title>
|
| 599 |
+
<style>
|
| 600 |
+
body { font-family: 'IBM Plex Sans Arabic', Arial, sans-serif; margin: 20px; background: #0A0A0A; color: #E0E0E0; }
|
| 601 |
+
.header { background: linear-gradient(135deg, #00E0D5, #00B8B8); color: #0A0A0A; padding: 20px; border-radius: 10px; margin-bottom: 20px; }
|
| 602 |
+
.section { background: #1A1A1A; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 1px solid #333; }
|
| 603 |
+
.threat { background: #2A2A2A; padding: 15px; margin: 10px 0; border-radius: 8px; border-left: 4px solid #FF4444; }
|
| 604 |
+
.recommendation { background: #2A2A2A; padding: 15px; margin: 10px 0; border-radius: 8px; border-left: 4px solid #00E0D5; }
|
| 605 |
+
.risk-score { font-size: 2em; font-weight: bold; color: #FF4444; }
|
| 606 |
+
.severity-critical { border-left-color: #FF4444; }
|
| 607 |
+
.severity-high { border-left-color: #FF8800; }
|
| 608 |
+
.severity-medium { border-left-color: #FFAA00; }
|
| 609 |
+
.severity-low { border-left-color: #FFDD00; }
|
| 610 |
+
.code { background: #0D1117; padding: 10px; border-radius: 5px; font-family: 'JetBrains Mono', monospace; direction: ltr; }
|
| 611 |
+
</style>
|
| 612 |
+
</head>
|
| 613 |
+
<body>
|
| 614 |
+
<div class="header">
|
| 615 |
+
<h1>تقرير تحليل التهديدات الأمنية</h1>
|
| 616 |
+
<p>Security Threat Analysis Report</p>
|
| 617 |
+
<p>التاريخ: ${new Date(analysisResult.timestamp).toLocaleString('ar-SA')}</p>
|
| 618 |
+
<p>المصدر: ${analysisResult.source}</p>
|
| 619 |
+
<div class="risk-score">درجة المخاطر: ${analysisResult.riskScore}%</div>
|
| 620 |
+
</div>
|
| 621 |
+
|
| 622 |
+
<div class="section">
|
| 623 |
+
<h2>التهديدات المكتشفة</h2>
|
| 624 |
+
<p>Discovered Threats</p>
|
| 625 |
+
${analysisResult.threats.map(threat => `
|
| 626 |
+
<div class="threat severity-${threat.severity}">
|
| 627 |
+
<h3>${threat.type} - ${threat.severity}</h3>
|
| 628 |
+
<p><strong>النمط:</strong> <span class="code">${threat.pattern}</span></p>
|
| 629 |
+
<p><strong>التطابق:</strong> <span class="code">${threat.match}</span></p>
|
| 630 |
+
<p><strong>السطر:</strong> ${threat.line}</p>
|
| 631 |
+
<p><strong>التأثير:</strong> ${threat.impact}/10</p>
|
| 632 |
+
<p><strong>الاحتمالية:</strong> ${threat.likelihood}/10</p>
|
| 633 |
+
</div>
|
| 634 |
+
`).join('')}
|
| 635 |
+
</div>
|
| 636 |
+
|
| 637 |
+
<div class="section">
|
| 638 |
+
<h2>التوصيات الأمنية</h2>
|
| 639 |
+
<p>Security Recommendations</p>
|
| 640 |
+
${analysisResult.recommendations.map(rec => `
|
| 641 |
+
<div class="recommendation">
|
| 642 |
+
<h3>${rec.title}</h3>
|
| 643 |
+
<p><strong>الأولوية:</strong> ${rec.priority}</p>
|
| 644 |
+
<p><strong>الفئة:</strong> ${rec.category}</p>
|
| 645 |
+
<p><strong>الوصف:</strong> ${rec.description}</p>
|
| 646 |
+
<p><strong>التنفيذ:</strong></p>
|
| 647 |
+
<ul>
|
| 648 |
+
${rec.implementation.map(item => `<li>${item}</li>`).join('')}
|
| 649 |
+
</ul>
|
| 650 |
+
</div>
|
| 651 |
+
`).join('')}
|
| 652 |
+
</div>
|
| 653 |
+
|
| 654 |
+
<div class="section">
|
| 655 |
+
<h2>تفاصيل التحليل</h2>
|
| 656 |
+
<p>Analysis Details</p>
|
| 657 |
+
<pre class="code">${JSON.stringify(analysisResult.details, null, 2)}</pre>
|
| 658 |
+
</div>
|
| 659 |
+
</body>
|
| 660 |
+
</html>`;
|
| 661 |
+
}
|
| 662 |
+
|
| 663 |
+
/**
|
| 664 |
+
* الحصول على إحصائيات التحليل
|
| 665 |
+
* Get analysis statistics
|
| 666 |
+
*/
|
| 667 |
+
getStatistics() {
|
| 668 |
+
const totalAnalyses = this.analysisHistory.length;
|
| 669 |
+
const avgRiskScore = totalAnalyses > 0
|
| 670 |
+
? this.analysisHistory.reduce((sum, analysis) => sum + analysis.riskScore, 0) / totalAnalyses
|
| 671 |
+
: 0;
|
| 672 |
+
|
| 673 |
+
const threatCategories = {};
|
| 674 |
+
let criticalThreats = 0;
|
| 675 |
+
|
| 676 |
+
this.analysisHistory.forEach(analysis => {
|
| 677 |
+
analysis.threats.forEach(threat => {
|
| 678 |
+
threatCategories[threat.type] = (threatCategories[threat.type] || 0) + 1;
|
| 679 |
+
if (threat.severity === 'critical') criticalThreats++;
|
| 680 |
+
});
|
| 681 |
+
});
|
| 682 |
+
|
| 683 |
+
return {
|
| 684 |
+
totalAnalyses,
|
| 685 |
+
avgRiskScore: Math.round(avgRiskScore),
|
| 686 |
+
threatCategories,
|
| 687 |
+
criticalThreats,
|
| 688 |
+
lastAnalysis: totalAnalyses > 0 ? this.analysisHistory[this.analysisHistory.length - 1].timestamp : null
|
| 689 |
+
};
|
| 690 |
+
}
|
| 691 |
+
}
|
| 692 |
+
|
| 693 |
+
// تصدير الكلاس للاستخدام
|
| 694 |
+
window.AIThreatAnalyzer = AIThreatAnalyzer;
|
js/components.js
ADDED
|
@@ -0,0 +1,787 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ==============================================
|
| 2 |
+
مكونات تفاعلية - مشروع سياسة أمان المحتوى
|
| 3 |
+
Interactive Components JavaScript
|
| 4 |
+
============================================== */
|
| 5 |
+
|
| 6 |
+
// Example Tabs Functionality
|
| 7 |
+
function showExampleTab(tabName) {
|
| 8 |
+
// Hide all example content
|
| 9 |
+
const exampleContents = document.querySelectorAll('.example-content');
|
| 10 |
+
exampleContents.forEach(content => {
|
| 11 |
+
content.classList.remove('active');
|
| 12 |
+
});
|
| 13 |
+
|
| 14 |
+
// Remove active class from all tabs
|
| 15 |
+
const tabButtons = document.querySelectorAll('.examples-tabs .tab-btn');
|
| 16 |
+
tabButtons.forEach(btn => {
|
| 17 |
+
btn.classList.remove('active');
|
| 18 |
+
});
|
| 19 |
+
|
| 20 |
+
// Show selected example content
|
| 21 |
+
const selectedContent = document.getElementById(tabName + '-example');
|
| 22 |
+
if (selectedContent) {
|
| 23 |
+
selectedContent.classList.add('active');
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
// Add active class to clicked tab
|
| 27 |
+
const clickedTab = event.target;
|
| 28 |
+
clickedTab.classList.add('active');
|
| 29 |
+
|
| 30 |
+
// Announce change for screen readers
|
| 31 |
+
CSPProject.announceMessage(`تم التبديل إلى ${tabName} example`);
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
// Guide Section Functionality
|
| 35 |
+
function showSection(sectionName) {
|
| 36 |
+
const targetSection = document.getElementById(sectionName);
|
| 37 |
+
if (targetSection) {
|
| 38 |
+
const navbarHeight = document.querySelector('.navbar').offsetHeight;
|
| 39 |
+
const elementPosition = targetSection.offsetTop - navbarHeight - 20;
|
| 40 |
+
|
| 41 |
+
window.scrollTo({
|
| 42 |
+
top: elementPosition,
|
| 43 |
+
behavior: 'smooth'
|
| 44 |
+
});
|
| 45 |
+
|
| 46 |
+
// Highlight the section
|
| 47 |
+
targetSection.style.border = '2px solid var(--primary-500)';
|
| 48 |
+
targetSection.style.borderRadius = '12px';
|
| 49 |
+
targetSection.style.padding = 'var(--space-lg)';
|
| 50 |
+
targetSection.style.margin = 'var(--space-lg)';
|
| 51 |
+
targetSection.style.background = 'rgba(0, 224, 213, 0.05)';
|
| 52 |
+
|
| 53 |
+
setTimeout(() => {
|
| 54 |
+
targetSection.style.border = '';
|
| 55 |
+
targetSection.style.borderRadius = '';
|
| 56 |
+
targetSection.style.padding = '';
|
| 57 |
+
targetSection.style.margin = '';
|
| 58 |
+
targetSection.style.background = '';
|
| 59 |
+
}, 2000);
|
| 60 |
+
|
| 61 |
+
CSPProject.announceMessage(`تم الانتقال إلى قسم ${sectionName}`);
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
// Modal Management
|
| 66 |
+
function openModal(modalId) {
|
| 67 |
+
const modal = document.getElementById(modalId);
|
| 68 |
+
if (modal) {
|
| 69 |
+
modal.classList.add('active');
|
| 70 |
+
document.body.style.overflow = 'hidden';
|
| 71 |
+
|
| 72 |
+
// Focus first input in modal
|
| 73 |
+
const firstInput = modal.querySelector('input, button, textarea, select');
|
| 74 |
+
if (firstInput) {
|
| 75 |
+
setTimeout(() => firstInput.focus(), 100);
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
CSPProject.announceMessage('تم فتح نافذة منبثقة');
|
| 79 |
+
}
|
| 80 |
+
}
|
| 81 |
+
|
| 82 |
+
function closeModal(modalId) {
|
| 83 |
+
const modal = document.getElementById(modalId);
|
| 84 |
+
if (modal) {
|
| 85 |
+
modal.classList.remove('active');
|
| 86 |
+
document.body.style.overflow = '';
|
| 87 |
+
CSPProject.announceMessage('تم إغلاق النافذة المنبثقة');
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
// CSP Builder Modal
|
| 92 |
+
function openCSPBuilder() {
|
| 93 |
+
openModal('cspBuilderModal');
|
| 94 |
+
initializeCSPBuilder();
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
function closeCSPBuilder() {
|
| 98 |
+
closeModal('cspBuilderModal');
|
| 99 |
+
}
|
| 100 |
+
|
| 101 |
+
// CSP Builder Functionality
|
| 102 |
+
function initializeCSPBuilder() {
|
| 103 |
+
const builderTabs = document.querySelectorAll('.builder-tabs .tab-btn');
|
| 104 |
+
const builderTabContents = document.querySelectorAll('.builder-tab');
|
| 105 |
+
|
| 106 |
+
builderTabs.forEach(tab => {
|
| 107 |
+
tab.addEventListener('click', function() {
|
| 108 |
+
const tabName = this.textContent.toLowerCase().replace(/\s+/g, '-');
|
| 109 |
+
showBuilderTab(tabName);
|
| 110 |
+
});
|
| 111 |
+
});
|
| 112 |
+
|
| 113 |
+
// Initialize form handlers
|
| 114 |
+
initializeBuilderForm();
|
| 115 |
+
generateInitialCSP();
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
function showBuilderTab(tabName) {
|
| 119 |
+
// Hide all builder tabs
|
| 120 |
+
builderTabContents.forEach(content => {
|
| 121 |
+
content.classList.remove('active');
|
| 122 |
+
});
|
| 123 |
+
|
| 124 |
+
// Remove active class from all builder tabs
|
| 125 |
+
const builderTabButtons = document.querySelectorAll('.builder-tabs .tab-btn');
|
| 126 |
+
builderTabButtons.forEach(btn => {
|
| 127 |
+
btn.classList.remove('active');
|
| 128 |
+
});
|
| 129 |
+
|
| 130 |
+
// Show selected builder tab
|
| 131 |
+
const selectedTab = document.getElementById(tabName + '-builder');
|
| 132 |
+
if (selectedTab) {
|
| 133 |
+
selectedTab.classList.add('active');
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
// Add active class to clicked tab
|
| 137 |
+
event.target.classList.add('active');
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
function initializeBuilderForm() {
|
| 141 |
+
const inputs = document.querySelectorAll('#cspBuilderModal input, #cspBuilderModal textarea');
|
| 142 |
+
|
| 143 |
+
inputs.forEach(input => {
|
| 144 |
+
input.addEventListener('input', CSPProject.debounce(generateCSPFromForm, 300));
|
| 145 |
+
});
|
| 146 |
+
|
| 147 |
+
const checkboxes = document.querySelectorAll('#cspBuilderModal input[type="checkbox"]');
|
| 148 |
+
checkboxes.forEach(checkbox => {
|
| 149 |
+
checkbox.addEventListener('change', generateCSPFromForm);
|
| 150 |
+
});
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
function generateInitialCSP() {
|
| 154 |
+
// Set default values
|
| 155 |
+
document.getElementById('jsSources').value = "'self' 'unsafe-inline'";
|
| 156 |
+
document.getElementById('cssSources').value = "'self' 'unsafe-inline'";
|
| 157 |
+
document.getElementById('imgSources').value = "'self' data: https:";
|
| 158 |
+
document.getElementById('fontSources').value = "'self'";
|
| 159 |
+
document.getElementById('connectSources').value = "'self'";
|
| 160 |
+
|
| 161 |
+
// Set default checkboxes
|
| 162 |
+
document.getElementById('blockMixedContent').checked = true;
|
| 163 |
+
document.getElementById('upgradeInsecure').checked = true;
|
| 164 |
+
document.getElementById('frameAncestors').checked = false;
|
| 165 |
+
|
| 166 |
+
generateCSPFromForm();
|
| 167 |
+
}
|
| 168 |
+
|
| 169 |
+
function generateCSPFromForm() {
|
| 170 |
+
const jsSources = document.getElementById('jsSources').value || "'self'";
|
| 171 |
+
const cssSources = document.getElementById('cssSources').value || "'self'";
|
| 172 |
+
const imgSources = document.getElementById('imgSources').value || "'self'";
|
| 173 |
+
const fontSources = document.getElementById('fontSources').value || "'self'";
|
| 174 |
+
const connectSources = document.getElementById('connectSources').value || "'self'";
|
| 175 |
+
|
| 176 |
+
const blockMixedContent = document.getElementById('blockMixedContent').checked;
|
| 177 |
+
const upgradeInsecure = document.getElementById('upgradeInsecure').checked;
|
| 178 |
+
const frameAncestors = document.getElementById('frameAncestors').checked;
|
| 179 |
+
const strictDynamic = document.getElementById('strictDynamic').checked;
|
| 180 |
+
|
| 181 |
+
let csp = "default-src 'self';\n";
|
| 182 |
+
csp += `script-src ${jsSources};\n`;
|
| 183 |
+
csp += `style-src ${cssSources};\n`;
|
| 184 |
+
csp += `img-src ${imgSources};\n`;
|
| 185 |
+
csp += `font-src ${fontSources};\n`;
|
| 186 |
+
csp += `connect-src ${connectSources};\n`;
|
| 187 |
+
|
| 188 |
+
if (strictDynamic) {
|
| 189 |
+
csp += "script-src 'strict-dynamic';\n";
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
if (frameAncestors) {
|
| 193 |
+
csp += "frame-ancestors 'self';\n";
|
| 194 |
+
} else {
|
| 195 |
+
csp += "frame-ancestors 'none';\n";
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
csp += "base-uri 'self';\n";
|
| 199 |
+
csp += "form-action 'self';\n";
|
| 200 |
+
|
| 201 |
+
if (blockMixedContent) {
|
| 202 |
+
csp += "block-all-mixed-content;\n";
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
if (upgradeInsecure) {
|
| 206 |
+
csp += "upgrade-insecure-requests;\n";
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
// Update the generated CSP display
|
| 210 |
+
const generatedCSP = document.getElementById('generatedCSP');
|
| 211 |
+
if (generatedCSP) {
|
| 212 |
+
generatedCSP.textContent = csp;
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
// Run tests
|
| 216 |
+
runCSPTests(csp);
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
function copyGeneratedCSP() {
|
| 220 |
+
const generatedCSP = document.getElementById('generatedCSP');
|
| 221 |
+
if (generatedCSP) {
|
| 222 |
+
CSPProject.copyToClipboard(generatedCSP.textContent);
|
| 223 |
+
showCopyFeedback();
|
| 224 |
+
}
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
function runCSPTests(csp) {
|
| 228 |
+
const testResults = document.querySelector('.test-results');
|
| 229 |
+
if (!testResults) return;
|
| 230 |
+
|
| 231 |
+
// Clear existing tests
|
| 232 |
+
testResults.innerHTML = '';
|
| 233 |
+
|
| 234 |
+
const tests = [
|
| 235 |
+
{
|
| 236 |
+
name: 'Default-src Policy',
|
| 237 |
+
check: () => csp.includes('default-src'),
|
| 238 |
+
status: csp.includes('default-src') ? 'success' : 'error'
|
| 239 |
+
},
|
| 240 |
+
{
|
| 241 |
+
name: 'Script-src Validation',
|
| 242 |
+
check: () => csp.includes('script-src'),
|
| 243 |
+
status: csp.includes('script-src') ? 'success' : 'error'
|
| 244 |
+
},
|
| 245 |
+
{
|
| 246 |
+
name: 'Unsafe-inline Warning',
|
| 247 |
+
check: () => !csp.includes("'unsafe-inline'") || csp.includes('script-src'),
|
| 248 |
+
status: csp.includes("'unsafe-inline'") ? 'warning' : 'success'
|
| 249 |
+
},
|
| 250 |
+
{
|
| 251 |
+
name: 'Frame Protection',
|
| 252 |
+
check: () => csp.includes('frame-ancestors'),
|
| 253 |
+
status: csp.includes('frame-ancestors') ? 'success' : 'warning'
|
| 254 |
+
},
|
| 255 |
+
{
|
| 256 |
+
name: 'Mixed Content Protection',
|
| 257 |
+
check: () => csp.includes('block-all-mixed-content'),
|
| 258 |
+
status: csp.includes('block-all-mixed-content') ? 'success' : 'warning'
|
| 259 |
+
}
|
| 260 |
+
];
|
| 261 |
+
|
| 262 |
+
tests.forEach(test => {
|
| 263 |
+
const testItem = document.createElement('div');
|
| 264 |
+
testItem.className = 'test-item';
|
| 265 |
+
|
| 266 |
+
const statusIcon = document.createElement('span');
|
| 267 |
+
statusIcon.className = `test-status ${test.status}`;
|
| 268 |
+
statusIcon.textContent = test.status === 'success' ? '✓' : test.status === 'warning' ? '⚠' : '✗';
|
| 269 |
+
|
| 270 |
+
const statusText = document.createElement('span');
|
| 271 |
+
statusText.textContent = test.name;
|
| 272 |
+
|
| 273 |
+
testItem.appendChild(statusIcon);
|
| 274 |
+
testItem.appendChild(statusText);
|
| 275 |
+
testResults.appendChild(testItem);
|
| 276 |
+
});
|
| 277 |
+
}
|
| 278 |
+
|
| 279 |
+
// CSP Tester Modal
|
| 280 |
+
function openCSPTester() {
|
| 281 |
+
showModalWithContent('cspTesterModal', `
|
| 282 |
+
<div class="modal-header">
|
| 283 |
+
<h3>🔍 اختبار سياسة أمان المحتوى</h3>
|
| 284 |
+
<button class="modal-close" onclick="closeModal('cspTesterModal')">×</button>
|
| 285 |
+
</div>
|
| 286 |
+
<div class="modal-body">
|
| 287 |
+
<div class="test-input-section">
|
| 288 |
+
<h4>أدخل سياسة CSP للاختبار:</h4>
|
| 289 |
+
<textarea id="cspToTest" placeholder="الصق سياسة CSP هنا..." rows="8"></textarea>
|
| 290 |
+
<button class="btn btn-primary" onclick="analyzeCSP()">تحليل السياسة</button>
|
| 291 |
+
</div>
|
| 292 |
+
<div id="testResults" class="test-results" style="margin-top: 20px;"></div>
|
| 293 |
+
</div>
|
| 294 |
+
`);
|
| 295 |
+
}
|
| 296 |
+
|
| 297 |
+
function analyzeCSP() {
|
| 298 |
+
const cspInput = document.getElementById('cspToTest');
|
| 299 |
+
const results = document.getElementById('testResults');
|
| 300 |
+
|
| 301 |
+
if (!cspInput || !results) return;
|
| 302 |
+
|
| 303 |
+
const csp = cspInput.value.trim();
|
| 304 |
+
if (!csp) {
|
| 305 |
+
results.innerHTML = '<div class="status-message error">يرجى إدخال سياسة CSP للاختبار</div>';
|
| 306 |
+
return;
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
results.innerHTML = '<div class="status-message loading"><div class="loading-spinner"></div>جاري تحليل السياسة...</div>';
|
| 310 |
+
|
| 311 |
+
setTimeout(() => {
|
| 312 |
+
const analysis = performCSPAnalysis(csp);
|
| 313 |
+
displayCSPAnalysis(analysis, results);
|
| 314 |
+
}, 1000);
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
function performCSPAnalysis(csp) {
|
| 318 |
+
const directives = csp.split(';').map(d => d.trim()).filter(d => d);
|
| 319 |
+
const analysis = {
|
| 320 |
+
directives: [],
|
| 321 |
+
securityScore: 0,
|
| 322 |
+
recommendations: [],
|
| 323 |
+
vulnerabilities: []
|
| 324 |
+
};
|
| 325 |
+
|
| 326 |
+
directives.forEach(directive => {
|
| 327 |
+
const [name, ...values] = directive.split(/\s+/);
|
| 328 |
+
const directiveAnalysis = analyzeDirective(name, values.join(' '));
|
| 329 |
+
analysis.directives.push(directiveAnalysis);
|
| 330 |
+
analysis.securityScore += directiveAnalysis.score;
|
| 331 |
+
});
|
| 332 |
+
|
| 333 |
+
// Overall recommendations
|
| 334 |
+
if (!csp.includes('default-src')) {
|
| 335 |
+
analysis.recommendations.push('إضافة default-src لتحديد السياسة الافتراضية');
|
| 336 |
+
}
|
| 337 |
+
if (csp.includes("'unsafe-inline'") && csp.includes('script-src')) {
|
| 338 |
+
analysis.vulnerabilities.push("'unsafe-inline' في script-src يسمح بتنفيذ JavaScript ضار");
|
| 339 |
+
}
|
| 340 |
+
if (!csp.includes('frame-ancestors')) {
|
| 341 |
+
analysis.recommendations.push('إضافة frame-ancestors لمنع clickjacking');
|
| 342 |
+
}
|
| 343 |
+
if (!csp.includes('object-src')) {
|
| 344 |
+
analysis.recommendations.push('إضافة object-src \'none\' لمنع plugins خطرة');
|
| 345 |
+
}
|
| 346 |
+
|
| 347 |
+
analysis.securityScore = Math.min(100, Math.max(0, analysis.securityScore));
|
| 348 |
+
|
| 349 |
+
return analysis;
|
| 350 |
+
}
|
| 351 |
+
|
| 352 |
+
function analyzeDirective(name, values) {
|
| 353 |
+
const directive = {
|
| 354 |
+
name: name,
|
| 355 |
+
values: values,
|
| 356 |
+
score: 0,
|
| 357 |
+
issues: [],
|
| 358 |
+
recommendations: []
|
| 359 |
+
};
|
| 360 |
+
|
| 361 |
+
switch (name) {
|
| 362 |
+
case 'default-src':
|
| 363 |
+
directive.score = 20;
|
| 364 |
+
if (!values.includes("'self'")) {
|
| 365 |
+
directive.issues.push("يفضل إضافة 'self' كقيمة افتراضية");
|
| 366 |
+
directive.score -= 5;
|
| 367 |
+
}
|
| 368 |
+
break;
|
| 369 |
+
|
| 370 |
+
case 'script-src':
|
| 371 |
+
directive.score = 30;
|
| 372 |
+
if (values.includes("'unsafe-inline'")) {
|
| 373 |
+
directive.issues.push("'unsafe-inline' يسمح بتنفيذ JavaScript ضار");
|
| 374 |
+
directive.score -= 10;
|
| 375 |
+
}
|
| 376 |
+
if (values.includes("'unsafe-eval'")) {
|
| 377 |
+
directive.issues.push("'unsafe-eval' يسمح بـ code injection");
|
| 378 |
+
directive.score -= 10;
|
| 379 |
+
}
|
| 380 |
+
if (values.includes('*')) {
|
| 381 |
+
directive.issues.push("* يسمح بجميع المصادر");
|
| 382 |
+
directive.score -= 15;
|
| 383 |
+
}
|
| 384 |
+
break;
|
| 385 |
+
|
| 386 |
+
case 'style-src':
|
| 387 |
+
directive.score = 15;
|
| 388 |
+
if (values.includes("'unsafe-inline'")) {
|
| 389 |
+
directive.recommendations.push("استخدم nonces أو hashes بدلاً من 'unsafe-inline'");
|
| 390 |
+
directive.score -= 5;
|
| 391 |
+
}
|
| 392 |
+
break;
|
| 393 |
+
|
| 394 |
+
case 'frame-ancestors':
|
| 395 |
+
directive.score = 15;
|
| 396 |
+
if (values.includes('*')) {
|
| 397 |
+
directive.issues.push("* يسمح بجميع المواقع بتضمين موقعك");
|
| 398 |
+
directive.score -= 10;
|
| 399 |
+
}
|
| 400 |
+
break;
|
| 401 |
+
|
| 402 |
+
default:
|
| 403 |
+
directive.score = 5;
|
| 404 |
+
}
|
| 405 |
+
|
| 406 |
+
return directive;
|
| 407 |
+
}
|
| 408 |
+
|
| 409 |
+
function displayCSPAnalysis(analysis, container) {
|
| 410 |
+
const scoreColor = analysis.securityScore >= 80 ? 'success' :
|
| 411 |
+
analysis.securityScore >= 60 ? 'warning' : 'error';
|
| 412 |
+
|
| 413 |
+
container.innerHTML = `
|
| 414 |
+
<div class="analysis-summary">
|
| 415 |
+
<h4>📊 نتيجة التحليل:</h4>
|
| 416 |
+
<div class="security-status ${scoreColor}">
|
| 417 |
+
<div class="security-status-icon"></div>
|
| 418 |
+
<span>النتيجة: ${analysis.securityScore}/100</span>
|
| 419 |
+
</div>
|
| 420 |
+
</div>
|
| 421 |
+
|
| 422 |
+
<div class="directives-analysis">
|
| 423 |
+
<h4>📋 تحليل التوجيهات:</h4>
|
| 424 |
+
${analysis.directives.map(directive => `
|
| 425 |
+
<div class="directive-item">
|
| 426 |
+
<h5>${directive.name}</h5>
|
| 427 |
+
<p><strong>القيم:</strong> ${directive.values}</p>
|
| 428 |
+
<p><strong>النقاط:</strong> ${directive.score}/30</p>
|
| 429 |
+
${directive.issues.length > 0 ? `
|
| 430 |
+
<div class="security-alert error">
|
| 431 |
+
<div class="security-alert-icon">⚠️</div>
|
| 432 |
+
<div>
|
| 433 |
+
<strong>مشاكل:</strong>
|
| 434 |
+
<ul>${directive.issues.map(issue => `<li>${issue}</li>`).join('')}</ul>
|
| 435 |
+
</div>
|
| 436 |
+
</div>
|
| 437 |
+
` : ''}
|
| 438 |
+
${directive.recommendations.length > 0 ? `
|
| 439 |
+
<div class="security-alert warning">
|
| 440 |
+
<div class="security-alert-icon">💡</div>
|
| 441 |
+
<div>
|
| 442 |
+
<strong>توصيات:</strong>
|
| 443 |
+
<ul>${directive.recommendations.map(rec => `<li>${rec}</li>`).join('')}</ul>
|
| 444 |
+
</div>
|
| 445 |
+
</div>
|
| 446 |
+
` : ''}
|
| 447 |
+
</div>
|
| 448 |
+
`).join('')}
|
| 449 |
+
</div>
|
| 450 |
+
|
| 451 |
+
${analysis.vulnerabilities.length > 0 ? `
|
| 452 |
+
<div class="security-alert error">
|
| 453 |
+
<div class="security-alert-icon">🚨</div>
|
| 454 |
+
<div>
|
| 455 |
+
<strong>ثغرات أمنية مكتشفة:</strong>
|
| 456 |
+
<ul>${analysis.vulnerabilities.map(vuln => `<li>${vuln}</li>`).join('')}</ul>
|
| 457 |
+
</div>
|
| 458 |
+
</div>
|
| 459 |
+
` : ''}
|
| 460 |
+
|
| 461 |
+
${analysis.recommendations.length > 0 ? `
|
| 462 |
+
<div class="security-alert warning">
|
| 463 |
+
<div class="security-alert-icon">💡</div>
|
| 464 |
+
<div>
|
| 465 |
+
<strong>توصيات التحسين:</strong>
|
| 466 |
+
<ul>${analysis.recommendations.map(rec => `<li>${rec}</li>`).join('')}</ul>
|
| 467 |
+
</div>
|
| 468 |
+
</div>
|
| 469 |
+
` : ''}
|
| 470 |
+
`;
|
| 471 |
+
}
|
| 472 |
+
|
| 473 |
+
// Security Scanner Modal
|
| 474 |
+
function openSecurityScanner() {
|
| 475 |
+
showModalWithContent('securityScannerModal', `
|
| 476 |
+
<div class="modal-header">
|
| 477 |
+
<h3>🛡️ ماسح الأمان الشامل</h3>
|
| 478 |
+
<button class="modal-close" onclick="closeModal('securityScannerModal')">×</button>
|
| 479 |
+
</div>
|
| 480 |
+
<div class="modal-body">
|
| 481 |
+
<div class="scanner-input-section">
|
| 482 |
+
<h4>أدخل رابط الموقع للفحص:</h4>
|
| 483 |
+
<input type="url" id="siteToScan" placeholder="https://example.com" />
|
| 484 |
+
<button class="btn btn-primary" onclick="scanWebsite()">بدء الفحص</button>
|
| 485 |
+
</div>
|
| 486 |
+
<div id="scanResults" class="scan-results" style="margin-top: 20px;"></div>
|
| 487 |
+
</div>
|
| 488 |
+
`);
|
| 489 |
+
}
|
| 490 |
+
|
| 491 |
+
function scanWebsite() {
|
| 492 |
+
const urlInput = document.getElementById('siteToScan');
|
| 493 |
+
const results = document.getElementById('scanResults');
|
| 494 |
+
|
| 495 |
+
if (!urlInput || !results) return;
|
| 496 |
+
|
| 497 |
+
const url = urlInput.value.trim();
|
| 498 |
+
if (!url) {
|
| 499 |
+
results.innerHTML = '<div class="status-message error">يرجى إدخال رابط صحيح</div>';
|
| 500 |
+
return;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
if (!CSPProject.isValidUrl(url)) {
|
| 504 |
+
results.innerHTML = '<div class="status-message error">رابط غير صحيح</div>';
|
| 505 |
+
return;
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
results.innerHTML = '<div class="status-message loading"><div class="loading-spinner"></div>جاري فحص الموقع...</div>';
|
| 509 |
+
|
| 510 |
+
// Simulate scanning process
|
| 511 |
+
setTimeout(() => {
|
| 512 |
+
const scanResults = performSecurityScan(url);
|
| 513 |
+
displayScanResults(scanResults, results);
|
| 514 |
+
}, 2000);
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
function performSecurityScan(url) {
|
| 518 |
+
// Simulate security scan results
|
| 519 |
+
return {
|
| 520 |
+
url: url,
|
| 521 |
+
timestamp: new Date().toLocaleString('ar-SA'),
|
| 522 |
+
cspStatus: Math.random() > 0.5 ? 'secure' : 'warning',
|
| 523 |
+
headersStatus: Math.random() > 0.7 ? 'secure' : 'warning',
|
| 524 |
+
xssVulnerability: Math.random() > 0.8,
|
| 525 |
+
mixedContent: Math.random() > 0.6,
|
| 526 |
+
score: Math.floor(Math.random() * 40) + 60,
|
| 527 |
+
findings: [
|
| 528 |
+
{
|
| 529 |
+
type: 'CSP',
|
| 530 |
+
severity: 'medium',
|
| 531 |
+
description: 'سياسة أمان المحتوى موجودة ولكن تحتاج تحسين',
|
| 532 |
+
recommendation: 'استخدم strict-dynamic وإزالة unsafe-inline'
|
| 533 |
+
},
|
| 534 |
+
{
|
| 535 |
+
type: 'Headers',
|
| 536 |
+
severity: 'low',
|
| 537 |
+
description: 'بعض رؤوس الأمان مفقودة',
|
| 538 |
+
recommendation: 'أضف X-Frame-Options و X-Content-Type-Options'
|
| 539 |
+
}
|
| 540 |
+
]
|
| 541 |
+
};
|
| 542 |
+
}
|
| 543 |
+
|
| 544 |
+
function displayScanResults(results, container) {
|
| 545 |
+
const overallStatus = results.score >= 80 ? 'success' :
|
| 546 |
+
results.score >= 60 ? 'warning' : 'error';
|
| 547 |
+
|
| 548 |
+
container.innerHTML = `
|
| 549 |
+
<div class="scan-summary">
|
| 550 |
+
<h4>🔍 نتائج الفحص:</h4>
|
| 551 |
+
<div class="security-status ${overallStatus}">
|
| 552 |
+
<div class="security-status-icon"></div>
|
| 553 |
+
<span>النتيجة الإجمالية: ${results.score}/100</span>
|
| 554 |
+
</div>
|
| 555 |
+
<p><strong>الموقع:</strong> ${results.url}</p>
|
| 556 |
+
<p><strong>وقت الفحص:</strong> ${results.timestamp}</p>
|
| 557 |
+
</div>
|
| 558 |
+
|
| 559 |
+
<div class="scan-findings">
|
| 560 |
+
<h4>📋 النتائج المفصلة:</h4>
|
| 561 |
+
${results.findings.map(finding => `
|
| 562 |
+
<div class="finding-item">
|
| 563 |
+
<div class="finding-header">
|
| 564 |
+
<span class="finding-type">${finding.type}</span>
|
| 565 |
+
<span class="finding-severity ${finding.severity}">${finding.severity}</span>
|
| 566 |
+
</div>
|
| 567 |
+
<p>${finding.description}</p>
|
| 568 |
+
<p class="finding-recommendation"><strong>التوصية:</strong> ${finding.recommendation}</p>
|
| 569 |
+
</div>
|
| 570 |
+
`).join('')}
|
| 571 |
+
</div>
|
| 572 |
+
|
| 573 |
+
<div class="scan-recommendations">
|
| 574 |
+
<h4>🎯 التوصيات:</h4>
|
| 575 |
+
<ul>
|
| 576 |
+
<li>تطبيق سياسة CSP شاملة</li>
|
| 577 |
+
<li>تفعيل HTTPS فقط</li>
|
| 578 |
+
<li>إضافة رؤوس الأمان المطلوبة</li>
|
| 579 |
+
<li>فحص دوري للثغرات الأمنية</li>
|
| 580 |
+
</ul>
|
| 581 |
+
</div>
|
| 582 |
+
`;
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
// Code Analyzer Modal
|
| 586 |
+
function openCodeAnalyzer() {
|
| 587 |
+
showModalWithContent('codeAnalyzerModal', `
|
| 588 |
+
<div class="modal-header">
|
| 589 |
+
<h3>🔬 محلل الكود الأمني</h3>
|
| 590 |
+
<button class="modal-close" onclick="closeModal('codeAnalyzerModal')">×</button>
|
| 591 |
+
</div>
|
| 592 |
+
<div class="modal-body">
|
| 593 |
+
<div class="analyzer-input-section">
|
| 594 |
+
<h4>أدخل كود JavaScript للتحليل:</h4>
|
| 595 |
+
<textarea id="codeToAnalyze" placeholder="الصق كود JavaScript هنا..." rows="10"></textarea>
|
| 596 |
+
<button class="btn btn-primary" onclick="analyzeCode()">تحليل الكود</button>
|
| 597 |
+
</div>
|
| 598 |
+
<div id="codeAnalysisResults" class="code-analysis-results" style="margin-top: 20px;"></div>
|
| 599 |
+
</div>
|
| 600 |
+
`);
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
function analyzeCode() {
|
| 604 |
+
const codeInput = document.getElementById('codeToAnalyze');
|
| 605 |
+
const results = document.getElementById('codeAnalysisResults');
|
| 606 |
+
|
| 607 |
+
if (!codeInput || !results) return;
|
| 608 |
+
|
| 609 |
+
const code = codeInput.value.trim();
|
| 610 |
+
if (!code) {
|
| 611 |
+
results.innerHTML = '<div class="status-message error">يرجى إدخال كود للتحليل</div>';
|
| 612 |
+
return;
|
| 613 |
+
}
|
| 614 |
+
|
| 615 |
+
results.innerHTML = '<div class="status-message loading"><div class="loading-spinner"></div>جاري تحليل الكود...</div>';
|
| 616 |
+
|
| 617 |
+
setTimeout(() => {
|
| 618 |
+
const analysis = performCodeAnalysis(code);
|
| 619 |
+
displayCodeAnalysis(analysis, results);
|
| 620 |
+
}, 1500);
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
function performCodeAnalysis(code) {
|
| 624 |
+
const issues = [];
|
| 625 |
+
const recommendations = [];
|
| 626 |
+
let securityScore = 100;
|
| 627 |
+
|
| 628 |
+
// Check for XSS vulnerabilities
|
| 629 |
+
if (code.includes('innerHTML') && !code.includes('DOMPurify')) {
|
| 630 |
+
issues.push({
|
| 631 |
+
type: 'XSS Risk',
|
| 632 |
+
severity: 'high',
|
| 633 |
+
description: 'استخدام innerHTML قد يؤدي إلى XSS',
|
| 634 |
+
line: findLineWithIssue(code, 'innerHTML')
|
| 635 |
+
});
|
| 636 |
+
securityScore -= 20;
|
| 637 |
+
}
|
| 638 |
+
|
| 639 |
+
if (code.includes('eval(')) {
|
| 640 |
+
issues.push({
|
| 641 |
+
type: 'Code Injection',
|
| 642 |
+
severity: 'critical',
|
| 643 |
+
description: 'eval() يسمح بتنفيذ كود ضار',
|
| 644 |
+
line: findLineWithIssue(code, 'eval')
|
| 645 |
+
});
|
| 646 |
+
securityScore -= 30;
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
if (code.includes('document.write')) {
|
| 650 |
+
issues.push({
|
| 651 |
+
type: 'XSS Risk',
|
| 652 |
+
severity: 'medium',
|
| 653 |
+
description: 'document.write يمكن أن يسبب XSS',
|
| 654 |
+
line: findLineWithIssue(code, 'document.write')
|
| 655 |
+
});
|
| 656 |
+
securityScore -= 15;
|
| 657 |
+
}
|
| 658 |
+
|
| 659 |
+
// Check for good practices
|
| 660 |
+
if (code.includes('trustedTypes') || code.includes('createPolicy')) {
|
| 661 |
+
recommendations.push('ممتاز! استخدام Trusted Types للحماية من XSS');
|
| 662 |
+
securityScore += 10;
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
if (code.includes('CSP') || code.includes('Content-Security-Policy')) {
|
| 666 |
+
recommendations.push('جيد! تطبيق سياسة أمان المحتوى');
|
| 667 |
+
securityScore += 5;
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
securityScore = Math.max(0, Math.min(100, securityScore));
|
| 671 |
+
|
| 672 |
+
return {
|
| 673 |
+
issues,
|
| 674 |
+
recommendations,
|
| 675 |
+
securityScore,
|
| 676 |
+
summary: {
|
| 677 |
+
totalLines: code.split('\n').length,
|
| 678 |
+
securityIssues: issues.length,
|
| 679 |
+
recommendations: recommendations.length
|
| 680 |
+
}
|
| 681 |
+
};
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
function findLineWithIssue(code, issue) {
|
| 685 |
+
const lines = code.split('\n');
|
| 686 |
+
for (let i = 0; i < lines.length; i++) {
|
| 687 |
+
if (lines[i].includes(issue)) {
|
| 688 |
+
return i + 1;
|
| 689 |
+
}
|
| 690 |
+
}
|
| 691 |
+
return null;
|
| 692 |
+
}
|
| 693 |
+
|
| 694 |
+
function displayCodeAnalysis(analysis, container) {
|
| 695 |
+
const status = analysis.securityScore >= 80 ? 'success' :
|
| 696 |
+
analysis.securityScore >= 60 ? 'warning' : 'error';
|
| 697 |
+
|
| 698 |
+
container.innerHTML = `
|
| 699 |
+
<div class="code-analysis-summary">
|
| 700 |
+
<h4>📊 تحليل الكود:</h4>
|
| 701 |
+
<div class="security-status ${status}">
|
| 702 |
+
<div class="security-status-icon"></div>
|
| 703 |
+
<span>نقاط الأمان: ${analysis.securityScore}/100</span>
|
| 704 |
+
</div>
|
| 705 |
+
<div class="analysis-stats">
|
| 706 |
+
<p><strong>عدد الأسطر:</strong> ${analysis.summary.totalLines}</p>
|
| 707 |
+
<p><strong>المشاكل الأمنية:</strong> ${analysis.summary.securityIssues}</p>
|
| 708 |
+
<p><strong>التوصيات:</strong> ${analysis.summary.recommendations}</p>
|
| 709 |
+
</div>
|
| 710 |
+
</div>
|
| 711 |
+
|
| 712 |
+
${analysis.issues.length > 0 ? `
|
| 713 |
+
<div class="code-issues">
|
| 714 |
+
<h4>⚠️ المشاكل المكتشفة:</h4>
|
| 715 |
+
${analysis.issues.map(issue => `
|
| 716 |
+
<div class="code-issue">
|
| 717 |
+
<div class="issue-header">
|
| 718 |
+
<span class="issue-type">${issue.type}</span>
|
| 719 |
+
<span class="issue-severity ${issue.severity}">${issue.severity}</span>
|
| 720 |
+
${issue.line ? `<span class="issue-line">السطر ${issue.line}</span>` : ''}
|
| 721 |
+
</div>
|
| 722 |
+
<p>${issue.description}</p>
|
| 723 |
+
</div>
|
| 724 |
+
`).join('')}
|
| 725 |
+
</div>
|
| 726 |
+
` : ''}
|
| 727 |
+
|
| 728 |
+
${analysis.recommendations.length > 0 ? `
|
| 729 |
+
<div class="code-recommendations">
|
| 730 |
+
<h4>💡 التوصيات:</h4>
|
| 731 |
+
${analysis.recommendations.map(rec => `
|
| 732 |
+
<div class="recommendation-item">
|
| 733 |
+
<div class="recommendation-icon">✓</div>
|
| 734 |
+
<p>${rec}</p>
|
| 735 |
+
</div>
|
| 736 |
+
`).join('')}
|
| 737 |
+
</div>
|
| 738 |
+
` : ''}
|
| 739 |
+
|
| 740 |
+
<div class="code-suggestions">
|
| 741 |
+
<h4>🚀 اقتراحات للتحسين:</h4>
|
| 742 |
+
<ul>
|
| 743 |
+
<li>استخدم DOMPurify لتنظيف HTML</li>
|
| 744 |
+
<li>طبق Trusted Types للحماية المتقدمة</li>
|
| 745 |
+
<li>تجنب eval() و innerHTML غير المنضبط</li>
|
| 746 |
+
<li>استخدم Content Security Policy</li>
|
| 747 |
+
<li>فحص المدخلات من المستخدمين</li>
|
| 748 |
+
</ul>
|
| 749 |
+
</div>
|
| 750 |
+
`;
|
| 751 |
+
}
|
| 752 |
+
|
| 753 |
+
// Helper function to show modal with custom content
|
| 754 |
+
function showModalWithContent(modalId, content) {
|
| 755 |
+
const modal = document.getElementById(modalId);
|
| 756 |
+
if (modal) {
|
| 757 |
+
modal.innerHTML = content;
|
| 758 |
+
modal.classList.add('active');
|
| 759 |
+
document.body.style.overflow = 'hidden';
|
| 760 |
+
|
| 761 |
+
// Focus first input
|
| 762 |
+
const firstInput = modal.querySelector('input, button, textarea, select');
|
| 763 |
+
if (firstInput) {
|
| 764 |
+
setTimeout(() => firstInput.focus(), 100);
|
| 765 |
+
}
|
| 766 |
+
}
|
| 767 |
+
}
|
| 768 |
+
|
| 769 |
+
// Initialize component event listeners
|
| 770 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 771 |
+
// Initialize modal close on outside click
|
| 772 |
+
document.addEventListener('click', function(e) {
|
| 773 |
+
if (e.target.classList.contains('modal')) {
|
| 774 |
+
closeModal(e.target.id);
|
| 775 |
+
}
|
| 776 |
+
});
|
| 777 |
+
|
| 778 |
+
// Initialize keyboard shortcuts
|
| 779 |
+
document.addEventListener('keydown', function(e) {
|
| 780 |
+
if (e.key === 'Escape') {
|
| 781 |
+
const activeModal = document.querySelector('.modal.active');
|
| 782 |
+
if (activeModal) {
|
| 783 |
+
closeModal(activeModal.id);
|
| 784 |
+
}
|
| 785 |
+
}
|
| 786 |
+
});
|
| 787 |
+
});
|
js/main.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* ==============================================
|
| 2 |
+
الوظائف الرئيسية - مشروع سياسة أمان المحتوى
|
| 3 |
+
Main JavaScript Functionality
|
| 4 |
+
============================================== */
|
| 5 |
+
|
| 6 |
+
// DOM Content Loaded
|
| 7 |
+
document.addEventListener('DOMContentLoaded', function() {
|
| 8 |
+
initializeApp();
|
| 9 |
+
});
|
| 10 |
+
|
| 11 |
+
// Initialize Application
|
| 12 |
+
function initializeApp() {
|
| 13 |
+
initializeNavigation();
|
| 14 |
+
initializeScrollEffects();
|
| 15 |
+
initializeAnimations();
|
| 16 |
+
initializeCodeHighlighting();
|
| 17 |
+
initializeTooltips();
|
| 18 |
+
initializeAccessibility();
|
| 19 |
+
initializePerformanceMonitoring();
|
| 20 |
+
console.log('🚀 مشروع سياسة أمان المحتوى تم تحميله بنجاح');
|
| 21 |
+
}
|
| 22 |
+
|
| 23 |
+
// Navigation Functions
|
| 24 |
+
function initializeNavigation() {
|
| 25 |
+
const navToggle = document.querySelector('.nav-toggle');
|
| 26 |
+
const navLinks = document.querySelector('.nav-links');
|
| 27 |
+
const navbar = document.querySelector('.navbar');
|
| 28 |
+
|
| 29 |
+
// Mobile navigation toggle
|
| 30 |
+
if (navToggle && navLinks) {
|
| 31 |
+
navToggle.addEventListener('click', function() {
|
| 32 |
+
navToggle.classList.toggle('active');
|
| 33 |
+
navLinks.classList.toggle('active');
|
| 34 |
+
|
| 35 |
+
// Prevent body scroll when menu is open
|
| 36 |
+
if (navLinks.classList.contains('active')) {
|
| 37 |
+
document.body.style.overflow = 'hidden';
|
| 38 |
+
} else {
|
| 39 |
+
document.body.style.overflow = '';
|
| 40 |
+
}
|
| 41 |
+
});
|
| 42 |
+
|
| 43 |
+
// Close mobile menu when clicking on links
|
| 44 |
+
const navLinkItems = document.querySelectorAll('.nav-link');
|
| 45 |
+
navLinkItems.forEach(link => {
|
| 46 |
+
link.addEventListener('click', function() {
|
| 47 |
+
navToggle.classList.remove('active');
|
| 48 |
+
navLinks.classList.remove('active');
|
| 49 |
+
document.body.style.overflow = '';
|
| 50 |
+
});
|
| 51 |
+
});
|
| 52 |
+
|
| 53 |
+
// Close mobile menu when clicking outside
|
| 54 |
+
document.addEventListener('click', function(event) {
|
| 55 |
+
if (!navToggle.contains(event.target) && !navLinks.contains(event.target)) {
|
| 56 |
+
navToggle.classList.remove('active');
|
| 57 |
+
navLinks.classList.remove('active');
|
| 58 |
+
document.body.style.overflow = '';
|
| 59 |
+
}
|
| 60 |
+
});
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
// Navbar scroll effect
|
| 64 |
+
if (navbar) {
|
| 65 |
+
window.addEventListener('scroll', function() {
|
| 66 |
+
if (window.scrollY > 50) {
|
| 67 |
+
navbar.style.background = 'rgba(20, 20, 20, 0.98)';
|
| 68 |
+
navbar.style.backdropFilter = 'blur(15px)';
|
| 69 |
+
} else {
|
| 70 |
+
navbar.style.background = 'rgba(20, 20, 20, 0.95)';
|
| 71 |
+
navbar.style.backdropFilter = 'blur(10px)';
|
| 72 |
+
}
|
| 73 |
+
});
|
| 74 |
+
}
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
// Scroll to section function
|
| 78 |
+
function scrollToSection(sectionId) {
|
| 79 |
+
const element = document.getElementById(sectionId);
|
| 80 |
+
if (element) {
|
| 81 |
+
const navbarHeight = document.querySelector('.navbar').offsetHeight;
|
| 82 |
+
const elementPosition = element.offsetTop - navbarHeight - 20;
|
| 83 |
+
|
| 84 |
+
window.scrollTo({
|
| 85 |
+
top: elementPosition,
|
| 86 |
+
behavior: 'smooth'
|
| 87 |
+
});
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
|
| 91 |
+
// Smooth scrolling for navigation links
|
| 92 |
+
function initializeScrollEffects() {
|
| 93 |
+
const navLinks = document.querySelectorAll('a[href^="#"]');
|
| 94 |
+
|
| 95 |
+
navLinks.forEach(link => {
|
| 96 |
+
link.addEventListener('click', function(e) {
|
| 97 |
+
e.preventDefault();
|
| 98 |
+
const targetId = this.getAttribute('href').substring(1);
|
| 99 |
+
scrollToSection(targetId);
|
| 100 |
+
});
|
| 101 |
+
});
|
| 102 |
+
|
| 103 |
+
// Intersection Observer for active navigation highlighting
|
| 104 |
+
const sections = document.querySelectorAll('section[id]');
|
| 105 |
+
const navLinkItems = document.querySelectorAll('.nav-link');
|
| 106 |
+
|
| 107 |
+
const observer = new IntersectionObserver((entries) => {
|
| 108 |
+
entries.forEach(entry => {
|
| 109 |
+
if (entry.isIntersecting) {
|
| 110 |
+
const activeLink = document.querySelector(`.nav-link[href="#${entry.target.id}"]`);
|
| 111 |
+
navLinkItems.forEach(link => link.classList.remove('active'));
|
| 112 |
+
if (activeLink) {
|
| 113 |
+
activeLink.classList.add('active');
|
| 114 |
+
}
|
| 115 |
+
}
|
| 116 |
+
});
|
| 117 |
+
}, {
|
| 118 |
+
threshold: 0.3,
|
| 119 |
+
rootMargin: '-100px 0px -50% 0px'
|
| 120 |
+
});
|
| 121 |
+
|
| 122 |
+
sections.forEach(section => observer.observe(section));
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
// Initialize animations
|
| 126 |
+
function initializeAnimations() {
|
| 127 |
+
// Fade in animation for elements
|
| 128 |
+
const animatedElements = document.querySelectorAll('.guide-card, .tool-card, .tech-card');
|
| 129 |
+
|
| 130 |
+
const animationObserver = new IntersectionObserver((entries) => {
|
| 131 |
+
entries.forEach((entry, index) => {
|
| 132 |
+
if (entry.isIntersecting) {
|
| 133 |
+
setTimeout(() => {
|
| 134 |
+
entry.target.style.opacity = '1';
|
| 135 |
+
entry.target.style.transform = 'translateY(0)';
|
| 136 |
+
}, index * 100);
|
| 137 |
+
animationObserver.unobserve(entry.target);
|
| 138 |
+
}
|
| 139 |
+
});
|
| 140 |
+
}, {
|
| 141 |
+
threshold: 0.1
|
| 142 |
+
});
|
| 143 |
+
|
| 144 |
+
animatedElements.forEach(element => {
|
| 145 |
+
element.style.opacity = '0';
|
| 146 |
+
element.style.transform = 'translateY(30px)';
|
| 147 |
+
element.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
|
| 148 |
+
animationObserver.observe(element);
|
| 149 |
+
});
|
| 150 |
+
|
| 151 |
+
// Parallax effect for hero section
|
| 152 |
+
const heroVisual = document.querySelector('.hero-visual');
|
| 153 |
+
if (heroVisual) {
|
| 154 |
+
window.addEventListener('scroll', function() {
|
| 155 |
+
const scrolled = window.pageYOffset;
|
| 156 |
+
const parallaxSpeed = 0.5;
|
| 157 |
+
heroVisual.style.transform = `translateY(${scrolled * parallaxSpeed}px)`;
|
| 158 |
+
});
|
| 159 |
+
}
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
// Code highlighting and copy functionality
|
| 163 |
+
function initializeCodeHighlighting() {
|
| 164 |
+
const codeBlocks = document.querySelectorAll('.code-container');
|
| 165 |
+
|
| 166 |
+
codeBlocks.forEach(block => {
|
| 167 |
+
// Add line numbers
|
| 168 |
+
const code = block.querySelector('code');
|
| 169 |
+
if (code && !code.classList.contains('no-line-numbers')) {
|
| 170 |
+
addLineNumbers(block);
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
// Add copy functionality
|
| 174 |
+
addCopyButton(block);
|
| 175 |
+
});
|
| 176 |
+
}
|
| 177 |
+
|
| 178 |
+
// Add line numbers to code blocks
|
| 179 |
+
function addLineNumbers(container) {
|
| 180 |
+
const code = container.querySelector('code');
|
| 181 |
+
if (!code) return;
|
| 182 |
+
|
| 183 |
+
const lines = code.textContent.split('\n');
|
| 184 |
+
const lineNumbersContainer = document.createElement('div');
|
| 185 |
+
lineNumbersContainer.className = 'code-line-numbers';
|
| 186 |
+
|
| 187 |
+
lines.forEach((_, index) => {
|
| 188 |
+
const lineNumber = document.createElement('span');
|
| 189 |
+
lineNumber.className = 'line-number';
|
| 190 |
+
lineNumber.textContent = index + 1;
|
| 191 |
+
lineNumbersContainer.appendChild(lineNumber);
|
| 192 |
+
});
|
| 193 |
+
|
| 194 |
+
const wrapper = document.createElement('div');
|
| 195 |
+
wrapper.className = 'code-block-wrapper';
|
| 196 |
+
wrapper.appendChild(lineNumbersContainer);
|
| 197 |
+
|
| 198 |
+
const content = document.createElement('div');
|
| 199 |
+
content.className = 'code-block-content';
|
| 200 |
+
content.appendChild(code);
|
| 201 |
+
|
| 202 |
+
wrapper.appendChild(content);
|
| 203 |
+
container.innerHTML = '';
|
| 204 |
+
container.appendChild(wrapper);
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
// Add copy button to code blocks
|
| 208 |
+
function addCopyButton(container) {
|
| 209 |
+
const copyButton = document.createElement('button');
|
| 210 |
+
copyButton.className = 'code-copy-btn';
|
| 211 |
+
copyButton.innerHTML = `
|
| 212 |
+
<svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16">
|
| 213 |
+
<path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/>
|
| 214 |
+
</svg>
|
| 215 |
+
نسخ
|
| 216 |
+
`;
|
| 217 |
+
|
| 218 |
+
copyButton.addEventListener('click', function() {
|
| 219 |
+
const code = container.querySelector('code');
|
| 220 |
+
if (code) {
|
| 221 |
+
copyToClipboard(code.textContent);
|
| 222 |
+
showCopyFeedback();
|
| 223 |
+
}
|
| 224 |
+
});
|
| 225 |
+
|
| 226 |
+
const header = container.previousElementSibling;
|
| 227 |
+
if (header && header.classList.contains('example-header')) {
|
| 228 |
+
header.appendChild(copyButton);
|
| 229 |
+
}
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
// Copy to clipboard functionality
|
| 233 |
+
function copyToClipboard(text) {
|
| 234 |
+
if (navigator.clipboard && window.isSecureContext) {
|
| 235 |
+
navigator.clipboard.writeText(text).catch(err => {
|
| 236 |
+
console.error('فشل في نسخ النص: ', err);
|
| 237 |
+
fallbackCopyToClipboard(text);
|
| 238 |
+
});
|
| 239 |
+
} else {
|
| 240 |
+
fallbackCopyToClipboard(text);
|
| 241 |
+
}
|
| 242 |
+
}
|
| 243 |
+
|
| 244 |
+
// Fallback copy method
|
| 245 |
+
function fallbackCopyToClipboard(text) {
|
| 246 |
+
const textArea = document.createElement('textarea');
|
| 247 |
+
textArea.value = text;
|
| 248 |
+
textArea.style.position = 'fixed';
|
| 249 |
+
textArea.style.left = '-999999px';
|
| 250 |
+
textArea.style.top = '-999999px';
|
| 251 |
+
document.body.appendChild(textArea);
|
| 252 |
+
textArea.focus();
|
| 253 |
+
textArea.select();
|
| 254 |
+
|
| 255 |
+
try {
|
| 256 |
+
document.execCommand('copy');
|
| 257 |
+
} catch (err) {
|
| 258 |
+
console.error('فشل في نسخ النص: ', err);
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
document.body.removeChild(textArea);
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
// Show copy feedback
|
| 265 |
+
function showCopyFeedback() {
|
| 266 |
+
const feedback = document.createElement('div');
|
| 267 |
+
feedback.className = 'copy-feedback';
|
| 268 |
+
feedback.textContent = 'تم النسخ بنجاح!';
|
| 269 |
+
document.body.appendChild(feedback);
|
| 270 |
+
|
| 271 |
+
setTimeout(() => {
|
| 272 |
+
document.body.removeChild(feedback);
|
| 273 |
+
}, 2000);
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
// Initialize tooltips
|
| 277 |
+
function initializeTooltips() {
|
| 278 |
+
const elementsWithTooltips = document.querySelectorAll('[data-tooltip]');
|
| 279 |
+
|
| 280 |
+
elementsWithTooltips.forEach(element => {
|
| 281 |
+
const tooltip = document.createElement('div');
|
| 282 |
+
tooltip.className = 'tooltip-content';
|
| 283 |
+
tooltip.textContent = element.getAttribute('data-tooltip');
|
| 284 |
+
|
| 285 |
+
const tooltipWrapper = document.createElement('div');
|
| 286 |
+
tooltipWrapper.className = 'tooltip';
|
| 287 |
+
tooltipWrapper.appendChild(tooltip);
|
| 288 |
+
|
| 289 |
+
element.parentNode.insertBefore(tooltipWrapper, element);
|
| 290 |
+
tooltipWrapper.appendChild(element);
|
| 291 |
+
});
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
// Accessibility enhancements
|
| 295 |
+
function initializeAccessibility() {
|
| 296 |
+
// Add skip link
|
| 297 |
+
const skipLink = document.createElement('a');
|
| 298 |
+
skipLink.href = '#main-content';
|
| 299 |
+
skipLink.className = 'skip-link';
|
| 300 |
+
skipLink.textContent = 'انتقل إلى المحتوى الرئيسي';
|
| 301 |
+
document.body.insertBefore(skipLink, document.body.firstChild);
|
| 302 |
+
|
| 303 |
+
// Add main content landmark
|
| 304 |
+
const heroSection = document.querySelector('#hero');
|
| 305 |
+
if (heroSection) {
|
| 306 |
+
heroSection.id = 'main-content';
|
| 307 |
+
heroSection.setAttribute('role', 'main');
|
| 308 |
+
}
|
| 309 |
+
|
| 310 |
+
// Enhanced keyboard navigation
|
| 311 |
+
const focusableElements = document.querySelectorAll(
|
| 312 |
+
'a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
|
| 313 |
+
);
|
| 314 |
+
|
| 315 |
+
// Trap focus in modals
|
| 316 |
+
const modals = document.querySelectorAll('.modal');
|
| 317 |
+
modals.forEach(modal => {
|
| 318 |
+
modal.addEventListener('keydown', function(e) {
|
| 319 |
+
if (e.key === 'Escape') {
|
| 320 |
+
closeModal(modal.id);
|
| 321 |
+
}
|
| 322 |
+
|
| 323 |
+
if (e.key === 'Tab') {
|
| 324 |
+
const focusable = modal.querySelectorAll(
|
| 325 |
+
'a, button, input, textarea, select, [tabindex]:not([tabindex="-1"])'
|
| 326 |
+
);
|
| 327 |
+
const firstFocusable = focusable[0];
|
| 328 |
+
const lastFocusable = focusable[focusable.length - 1];
|
| 329 |
+
|
| 330 |
+
if (e.shiftKey) {
|
| 331 |
+
if (document.activeElement === firstFocusable) {
|
| 332 |
+
lastFocusable.focus();
|
| 333 |
+
e.preventDefault();
|
| 334 |
+
}
|
| 335 |
+
} else {
|
| 336 |
+
if (document.activeElement === lastFocusable) {
|
| 337 |
+
firstFocusable.focus();
|
| 338 |
+
e.preventDefault();
|
| 339 |
+
}
|
| 340 |
+
}
|
| 341 |
+
}
|
| 342 |
+
});
|
| 343 |
+
});
|
| 344 |
+
|
| 345 |
+
// Announce dynamic content changes
|
| 346 |
+
const announcer = document.createElement('div');
|
| 347 |
+
announcer.setAttribute('aria-live', 'polite');
|
| 348 |
+
announcer.setAttribute('aria-atomic', 'true');
|
| 349 |
+
announcer.className = 'sr-only';
|
| 350 |
+
announcer.id = 'announcer';
|
| 351 |
+
document.body.appendChild(announcer);
|
| 352 |
+
}
|
| 353 |
+
|
| 354 |
+
// Announce message for screen readers
|
| 355 |
+
function announceMessage(message) {
|
| 356 |
+
const announcer = document.getElementById('announcer');
|
| 357 |
+
if (announcer) {
|
| 358 |
+
announcer.textContent = message;
|
| 359 |
+
setTimeout(() => {
|
| 360 |
+
announcer.textContent = '';
|
| 361 |
+
}, 1000);
|
| 362 |
+
}
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
// Performance monitoring
|
| 366 |
+
function initializePerformanceMonitoring() {
|
| 367 |
+
// Monitor Core Web Vitals
|
| 368 |
+
if ('PerformanceObserver' in window) {
|
| 369 |
+
// Largest Contentful Paint
|
| 370 |
+
const lcpObserver = new PerformanceObserver((list) => {
|
| 371 |
+
const entries = list.getEntries();
|
| 372 |
+
const lastEntry = entries[entries.length - 1];
|
| 373 |
+
console.log('🚀 LCP:', lastEntry.startTime);
|
| 374 |
+
});
|
| 375 |
+
lcpObserver.observe({entryTypes: ['largest-contentful-paint']});
|
| 376 |
+
|
| 377 |
+
// First Input Delay
|
| 378 |
+
const fidObserver = new PerformanceObserver((list) => {
|
| 379 |
+
const entries = list.getEntries();
|
| 380 |
+
entries.forEach(entry => {
|
| 381 |
+
console.log('🎯 FID:', entry.processingStart - entry.startTime);
|
| 382 |
+
});
|
| 383 |
+
});
|
| 384 |
+
fidObserver.observe({entryTypes: ['first-input']});
|
| 385 |
+
|
| 386 |
+
// Cumulative Layout Shift
|
| 387 |
+
let clsScore = 0;
|
| 388 |
+
const clsObserver = new PerformanceObserver((list) => {
|
| 389 |
+
const entries = list.getEntries();
|
| 390 |
+
entries.forEach(entry => {
|
| 391 |
+
if (!entry.hadRecentInput) {
|
| 392 |
+
clsScore += entry.value;
|
| 393 |
+
}
|
| 394 |
+
});
|
| 395 |
+
console.log('📊 CLS:', clsScore);
|
| 396 |
+
});
|
| 397 |
+
clsObserver.observe({entryTypes: ['layout-shift']});
|
| 398 |
+
}
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
// Utility Functions
|
| 402 |
+
function debounce(func, wait, immediate) {
|
| 403 |
+
let timeout;
|
| 404 |
+
return function executedFunction() {
|
| 405 |
+
const context = this;
|
| 406 |
+
const args = arguments;
|
| 407 |
+
const later = function() {
|
| 408 |
+
timeout = null;
|
| 409 |
+
if (!immediate) func.apply(context, args);
|
| 410 |
+
};
|
| 411 |
+
const callNow = immediate && !timeout;
|
| 412 |
+
clearTimeout(timeout);
|
| 413 |
+
timeout = setTimeout(later, wait);
|
| 414 |
+
if (callNow) func.apply(context, args);
|
| 415 |
+
};
|
| 416 |
+
}
|
| 417 |
+
|
| 418 |
+
function throttle(func, limit) {
|
| 419 |
+
let inThrottle;
|
| 420 |
+
return function() {
|
| 421 |
+
const args = arguments;
|
| 422 |
+
const context = this;
|
| 423 |
+
if (!inThrottle) {
|
| 424 |
+
func.apply(context, args);
|
| 425 |
+
inThrottle = true;
|
| 426 |
+
setTimeout(() => inThrottle = false, limit);
|
| 427 |
+
}
|
| 428 |
+
};
|
| 429 |
+
}
|
| 430 |
+
|
| 431 |
+
// Generate random nonce for CSP
|
| 432 |
+
function generateNonce() {
|
| 433 |
+
const array = new Uint8Array(16);
|
| 434 |
+
crypto.getRandomValues(array);
|
| 435 |
+
return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('');
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
// Calculate SHA-256 hash
|
| 439 |
+
async function calculateSHA256(text) {
|
| 440 |
+
const encoder = new TextEncoder();
|
| 441 |
+
const data = encoder.encode(text);
|
| 442 |
+
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
|
| 443 |
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
| 444 |
+
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
| 445 |
+
}
|
| 446 |
+
|
| 447 |
+
// Validate URL
|
| 448 |
+
function isValidUrl(string) {
|
| 449 |
+
try {
|
| 450 |
+
new URL(string);
|
| 451 |
+
return true;
|
| 452 |
+
} catch (_) {
|
| 453 |
+
return false;
|
| 454 |
+
}
|
| 455 |
+
}
|
| 456 |
+
|
| 457 |
+
// Sanitize HTML
|
| 458 |
+
function sanitizeHTML(html) {
|
| 459 |
+
const div = document.createElement('div');
|
| 460 |
+
div.textContent = html;
|
| 461 |
+
return div.innerHTML;
|
| 462 |
+
}
|
| 463 |
+
|
| 464 |
+
// Check browser support
|
| 465 |
+
function checkBrowserSupport() {
|
| 466 |
+
const support = {
|
| 467 |
+
csp: 'Content-Security-Policy' in document.head,
|
| 468 |
+
trustedTypes: 'trustedTypes' in window,
|
| 469 |
+
webAssembly: 'WebAssembly' in window,
|
| 470 |
+
serviceWorker: 'serviceWorker' in navigator,
|
| 471 |
+
intersectionObserver: 'IntersectionObserver' in window,
|
| 472 |
+
performanceObserver: 'PerformanceObserver' in window,
|
| 473 |
+
clipboard: 'clipboard' in navigator
|
| 474 |
+
};
|
| 475 |
+
|
| 476 |
+
console.log('🌐 Browser Support:', support);
|
| 477 |
+
return support;
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
// Error handling
|
| 481 |
+
window.addEventListener('error', function(e) {
|
| 482 |
+
console.error('❌ خطأ في التطبيق:', e.error);
|
| 483 |
+
// You could send error reports to analytics service here
|
| 484 |
+
});
|
| 485 |
+
|
| 486 |
+
window.addEventListener('unhandledrejection', function(e) {
|
| 487 |
+
console.error('❌ خطأ غير معالج في Promise:', e.reason);
|
| 488 |
+
e.preventDefault();
|
| 489 |
+
});
|
| 490 |
+
|
| 491 |
+
// Export functions for use in other modules
|
| 492 |
+
window.CSPProject = {
|
| 493 |
+
scrollToSection,
|
| 494 |
+
copyToClipboard,
|
| 495 |
+
generateNonce,
|
| 496 |
+
calculateSHA256,
|
| 497 |
+
isValidUrl,
|
| 498 |
+
sanitizeHTML,
|
| 499 |
+
checkBrowserSupport,
|
| 500 |
+
announceMessage,
|
| 501 |
+
debounce,
|
| 502 |
+
throttle
|
| 503 |
+
};
|
js/real-time-monitor.js
ADDED
|
@@ -0,0 +1,719 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* نظام المراقبة الأمنية في الوقت الفعلي
|
| 3 |
+
* Real-time Security Monitoring System
|
| 4 |
+
* Comprehensive security monitoring and alerting platform
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
class SecurityMonitor {
|
| 8 |
+
constructor() {
|
| 9 |
+
this.isMonitoring = false;
|
| 10 |
+
this.monitoringInterval = null;
|
| 11 |
+
this.alerts = [];
|
| 12 |
+
this.metrics = {
|
| 13 |
+
requests: 0,
|
| 14 |
+
blockedRequests: 0,
|
| 15 |
+
threats: 0,
|
| 16 |
+
responseTime: 0,
|
| 17 |
+
errors: 0
|
| 18 |
+
};
|
| 19 |
+
this.thresholds = {
|
| 20 |
+
responseTime: 5000, // 5 seconds
|
| 21 |
+
errorRate: 5, // 5%
|
| 22 |
+
threatRate: 10, // 10 threats per minute
|
| 23 |
+
blockedRate: 50 // 50% blocked requests
|
| 24 |
+
};
|
| 25 |
+
this.alertRules = [];
|
| 26 |
+
this.eventHandlers = new Map();
|
| 27 |
+
|
| 28 |
+
this.init();
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
/**
|
| 32 |
+
* تهيئة النظام
|
| 33 |
+
* Initialize the system
|
| 34 |
+
*/
|
| 35 |
+
init() {
|
| 36 |
+
this.setupEventListeners();
|
| 37 |
+
this.loadSavedConfig();
|
| 38 |
+
this.initializeMetrics();
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/**
|
| 42 |
+
* إعداد مستمعي الأحداث
|
| 43 |
+
* Setup event listeners
|
| 44 |
+
*/
|
| 45 |
+
setupEventListeners() {
|
| 46 |
+
// مراقبة طلبات الشبكة
|
| 47 |
+
if (window.fetch) {
|
| 48 |
+
const originalFetch = window.fetch;
|
| 49 |
+
window.fetch = (...args) => {
|
| 50 |
+
this.trackRequest('fetch', args);
|
| 51 |
+
return originalFetch.apply(window, args)
|
| 52 |
+
.then(response => {
|
| 53 |
+
this.trackResponse('fetch', response);
|
| 54 |
+
return response;
|
| 55 |
+
})
|
| 56 |
+
.catch(error => {
|
| 57 |
+
this.trackError('fetch', error);
|
| 58 |
+
throw error;
|
| 59 |
+
});
|
| 60 |
+
};
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
// مراقبة XMLHttpRequest
|
| 64 |
+
if (window.XMLHttpRequest) {
|
| 65 |
+
const OriginalXHR = window.XMLHttpRequest;
|
| 66 |
+
window.XMLHttpRequest = function() {
|
| 67 |
+
const xhr = new OriginalXHR();
|
| 68 |
+
const originalOpen = xhr.open;
|
| 69 |
+
const originalSend = xhr.send;
|
| 70 |
+
|
| 71 |
+
xhr.open = function(method, url, ...args) {
|
| 72 |
+
this._method = method;
|
| 73 |
+
this._url = url;
|
| 74 |
+
return originalOpen.apply(xhr, [method, url, ...args]);
|
| 75 |
+
};
|
| 76 |
+
|
| 77 |
+
xhr.send = function(...args) {
|
| 78 |
+
securityMonitor.trackRequest('xhr', { method: this._method, url: this._url });
|
| 79 |
+
|
| 80 |
+
xhr.addEventListener('load', () => {
|
| 81 |
+
securityMonitor.trackResponse('xhr', { status: xhr.status, url: this._url });
|
| 82 |
+
});
|
| 83 |
+
|
| 84 |
+
xhr.addEventListener('error', (error) => {
|
| 85 |
+
securityMonitor.trackError('xhr', error);
|
| 86 |
+
});
|
| 87 |
+
|
| 88 |
+
return originalSend.apply(xhr, args);
|
| 89 |
+
};
|
| 90 |
+
|
| 91 |
+
return xhr;
|
| 92 |
+
};
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
// مراقبة أخطاء JavaScript
|
| 96 |
+
window.addEventListener('error', (event) => {
|
| 97 |
+
this.trackError('javascript', {
|
| 98 |
+
message: event.message,
|
| 99 |
+
filename: event.filename,
|
| 100 |
+
lineno: event.lineno,
|
| 101 |
+
colno: event.colno,
|
| 102 |
+
error: event.error
|
| 103 |
+
});
|
| 104 |
+
});
|
| 105 |
+
|
| 106 |
+
// مراقبة أخطاء Promise
|
| 107 |
+
window.addEventListener('unhandledrejection', (event) => {
|
| 108 |
+
this.trackError('promise', {
|
| 109 |
+
reason: event.reason,
|
| 110 |
+
promise: event.promise
|
| 111 |
+
});
|
| 112 |
+
});
|
| 113 |
+
|
| 114 |
+
// مراقبة تغييرات DOM
|
| 115 |
+
if (window.MutationObserver) {
|
| 116 |
+
this.setupDOMMonitoring();
|
| 117 |
+
}
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
/**
|
| 121 |
+
* إعداد مراقبة DOM
|
| 122 |
+
* Setup DOM monitoring
|
| 123 |
+
*/
|
| 124 |
+
setupDOMMonitoring() {
|
| 125 |
+
const observer = new MutationObserver((mutations) => {
|
| 126 |
+
mutations.forEach((mutation) => {
|
| 127 |
+
// مراقبة إضافة عناصر جديدة
|
| 128 |
+
mutation.addedNodes.forEach((node) => {
|
| 129 |
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
| 130 |
+
this.analyzeNewElement(node);
|
| 131 |
+
}
|
| 132 |
+
});
|
| 133 |
+
|
| 134 |
+
// مراقبة تغييرات الخصائص
|
| 135 |
+
if (mutation.type === 'attributes') {
|
| 136 |
+
this.analyzeAttributeChange(mutation);
|
| 137 |
+
}
|
| 138 |
+
});
|
| 139 |
+
});
|
| 140 |
+
|
| 141 |
+
observer.observe(document.body, {
|
| 142 |
+
childList: true,
|
| 143 |
+
subtree: true,
|
| 144 |
+
attributes: true,
|
| 145 |
+
attributeOldValue: true
|
| 146 |
+
});
|
| 147 |
+
|
| 148 |
+
this.domObserver = observer;
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
/**
|
| 152 |
+
* تحليل عنصر جديد
|
| 153 |
+
* Analyze new element
|
| 154 |
+
*/
|
| 155 |
+
analyzeNewElement(element) {
|
| 156 |
+
const securityChecks = [
|
| 157 |
+
{
|
| 158 |
+
name: 'scriptInjection',
|
| 159 |
+
check: () => element.tagName === 'SCRIPT' && element.src,
|
| 160 |
+
severity: 'high',
|
| 161 |
+
message: 'تم إضافة عنصر script جديد'
|
| 162 |
+
},
|
| 163 |
+
{
|
| 164 |
+
name: 'iframeInjection',
|
| 165 |
+
check: () => element.tagName === 'IFRAME',
|
| 166 |
+
severity: 'medium',
|
| 167 |
+
message: 'تم إضافة iframe جديد'
|
| 168 |
+
},
|
| 169 |
+
{
|
| 170 |
+
name: 'formInjection',
|
| 171 |
+
check: () => element.tagName === 'FORM',
|
| 172 |
+
severity: 'low',
|
| 173 |
+
message: 'تم إضافة form جديد'
|
| 174 |
+
},
|
| 175 |
+
{
|
| 176 |
+
name: 'externalResource',
|
| 177 |
+
check: () => {
|
| 178 |
+
const src = element.getAttribute('src') || element.getAttribute('href');
|
| 179 |
+
return src && (src.startsWith('http://') || src.startsWith('//'));
|
| 180 |
+
},
|
| 181 |
+
severity: 'low',
|
| 182 |
+
message: 'تم إضافة مورد خارجي'
|
| 183 |
+
}
|
| 184 |
+
];
|
| 185 |
+
|
| 186 |
+
securityChecks.forEach(check => {
|
| 187 |
+
if (check.check()) {
|
| 188 |
+
this.triggerAlert({
|
| 189 |
+
type: 'domChange',
|
| 190 |
+
name: check.name,
|
| 191 |
+
severity: check.severity,
|
| 192 |
+
message: check.message,
|
| 193 |
+
element: {
|
| 194 |
+
tagName: element.tagName,
|
| 195 |
+
id: element.id,
|
| 196 |
+
className: element.className,
|
| 197 |
+
src: element.getAttribute('src'),
|
| 198 |
+
href: element.getAttribute('href')
|
| 199 |
+
},
|
| 200 |
+
timestamp: Date.now()
|
| 201 |
+
});
|
| 202 |
+
}
|
| 203 |
+
});
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
/**
|
| 207 |
+
* تحليل تغيير الخصائص
|
| 208 |
+
* Analyze attribute change
|
| 209 |
+
*/
|
| 210 |
+
analyzeAttributeChange(mutation) {
|
| 211 |
+
const dangerousAttributes = ['onclick', 'onload', 'onerror', 'onmouseover', 'innerHTML', 'outerHTML'];
|
| 212 |
+
const changedAttr = mutation.attributeName;
|
| 213 |
+
|
| 214 |
+
if (dangerousAttributes.includes(changedAttr)) {
|
| 215 |
+
this.triggerAlert({
|
| 216 |
+
type: 'attributeChange',
|
| 217 |
+
name: 'dangerousAttributeChange',
|
| 218 |
+
severity: 'high',
|
| 219 |
+
message: `تم تغيير خاصية خطيرة: ${changedAttr}`,
|
| 220 |
+
element: {
|
| 221 |
+
tagName: mutation.target.tagName,
|
| 222 |
+
id: mutation.target.id,
|
| 223 |
+
attribute: changedAttr,
|
| 224 |
+
oldValue: mutation.oldValue,
|
| 225 |
+
newValue: mutation.target.getAttribute(changedAttr)
|
| 226 |
+
},
|
| 227 |
+
timestamp: Date.now()
|
| 228 |
+
});
|
| 229 |
+
}
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
/**
|
| 233 |
+
* بدء المراقبة
|
| 234 |
+
* Start monitoring
|
| 235 |
+
*/
|
| 236 |
+
startMonitoring(interval = 1000) {
|
| 237 |
+
if (this.isMonitoring) {
|
| 238 |
+
console.warn('المراقبة نشطة بالفعل');
|
| 239 |
+
return;
|
| 240 |
+
}
|
| 241 |
+
|
| 242 |
+
this.isMonitoring = true;
|
| 243 |
+
this.monitoringInterval = setInterval(() => {
|
| 244 |
+
this.collectMetrics();
|
| 245 |
+
this.checkThresholds();
|
| 246 |
+
this.cleanupOldAlerts();
|
| 247 |
+
}, interval);
|
| 248 |
+
|
| 249 |
+
this.triggerEvent('monitoringStarted', { timestamp: Date.now() });
|
| 250 |
+
console.log('تم بدء المراقبة الأمنية في الوقت الفعلي');
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
/**
|
| 254 |
+
* إيقاف المراقبة
|
| 255 |
+
* Stop monitoring
|
| 256 |
+
*/
|
| 257 |
+
stopMonitoring() {
|
| 258 |
+
if (!this.isMonitoring) {
|
| 259 |
+
console.warn('المراقبة متوقفة بالفعل');
|
| 260 |
+
return;
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
this.isMonitoring = false;
|
| 264 |
+
if (this.monitoringInterval) {
|
| 265 |
+
clearInterval(this.monitoringInterval);
|
| 266 |
+
this.monitoringInterval = null;
|
| 267 |
+
}
|
| 268 |
+
|
| 269 |
+
this.triggerEvent('monitoringStopped', { timestamp: Date.now() });
|
| 270 |
+
console.log('تم إيقاف المراقبة الأمنية');
|
| 271 |
+
}
|
| 272 |
+
|
| 273 |
+
/**
|
| 274 |
+
* تتبع الطلب
|
| 275 |
+
* Track request
|
| 276 |
+
*/
|
| 277 |
+
trackRequest(type, data) {
|
| 278 |
+
const request = {
|
| 279 |
+
type: type,
|
| 280 |
+
timestamp: Date.now(),
|
| 281 |
+
data: data,
|
| 282 |
+
id: this.generateId()
|
| 283 |
+
};
|
| 284 |
+
|
| 285 |
+
this.metrics.requests++;
|
| 286 |
+
this.triggerEvent('requestTracked', request);
|
| 287 |
+
}
|
| 288 |
+
|
| 289 |
+
/**
|
| 290 |
+
* تتبع الاستجابة
|
| 291 |
+
* Track response
|
| 292 |
+
*/
|
| 293 |
+
trackResponse(type, data) {
|
| 294 |
+
const response = {
|
| 295 |
+
type: type,
|
| 296 |
+
timestamp: Date.now(),
|
| 297 |
+
data: data,
|
| 298 |
+
id: this.generateId(),
|
| 299 |
+
responseTime: Date.now() - this.getRequestTime(type)
|
| 300 |
+
};
|
| 301 |
+
|
| 302 |
+
// فحص إذا كان الطلب محظور
|
| 303 |
+
if (data.status >= 400) {
|
| 304 |
+
this.metrics.blockedRequests++;
|
| 305 |
+
this.triggerAlert({
|
| 306 |
+
type: 'blockedRequest',
|
| 307 |
+
severity: 'medium',
|
| 308 |
+
message: `طلب محظور: ${data.status}`,
|
| 309 |
+
data: response,
|
| 310 |
+
timestamp: Date.now()
|
| 311 |
+
});
|
| 312 |
+
}
|
| 313 |
+
|
| 314 |
+
// تحديث متوسط وقت الاستجابة
|
| 315 |
+
this.metrics.responseTime = (this.metrics.responseTime + response.responseTime) / 2;
|
| 316 |
+
|
| 317 |
+
this.triggerEvent('responseTracked', response);
|
| 318 |
+
}
|
| 319 |
+
|
| 320 |
+
/**
|
| 321 |
+
* تتبع الخطأ
|
| 322 |
+
* Track error
|
| 323 |
+
*/
|
| 324 |
+
trackError(type, error) {
|
| 325 |
+
const errorEvent = {
|
| 326 |
+
type: type,
|
| 327 |
+
timestamp: Date.now(),
|
| 328 |
+
error: error,
|
| 329 |
+
id: this.generateId()
|
| 330 |
+
};
|
| 331 |
+
|
| 332 |
+
this.metrics.errors++;
|
| 333 |
+
this.metrics.threats++;
|
| 334 |
+
|
| 335 |
+
this.triggerAlert({
|
| 336 |
+
type: 'error',
|
| 337 |
+
severity: 'high',
|
| 338 |
+
message: `خطأ ${type}: ${error.message || error}`,
|
| 339 |
+
data: errorEvent,
|
| 340 |
+
timestamp: Date.now()
|
| 341 |
+
});
|
| 342 |
+
|
| 343 |
+
this.triggerEvent('errorTracked', errorEvent);
|
| 344 |
+
}
|
| 345 |
+
|
| 346 |
+
/**
|
| 347 |
+
* جمع المقاييس
|
| 348 |
+
* Collect metrics
|
| 349 |
+
*/
|
| 350 |
+
collectMetrics() {
|
| 351 |
+
const now = Date.now();
|
| 352 |
+
const oneMinuteAgo = now - 60000;
|
| 353 |
+
|
| 354 |
+
// حساب المعدلات
|
| 355 |
+
const recentAlerts = this.alerts.filter(alert => alert.timestamp > oneMinuteAgo);
|
| 356 |
+
const recentRequests = this.metrics.requests; // مبسط
|
| 357 |
+
|
| 358 |
+
const metrics = {
|
| 359 |
+
...this.metrics,
|
| 360 |
+
alertRate: recentAlerts.length,
|
| 361 |
+
timestamp: now
|
| 362 |
+
};
|
| 363 |
+
|
| 364 |
+
this.triggerEvent('metricsCollected', metrics);
|
| 365 |
+
return metrics;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
/**
|
| 369 |
+
* فحص الحدود
|
| 370 |
+
* Check thresholds
|
| 371 |
+
*/
|
| 372 |
+
checkThresholds() {
|
| 373 |
+
const currentMetrics = this.collectMetrics();
|
| 374 |
+
|
| 375 |
+
// فحص وقت الاستجابة
|
| 376 |
+
if (currentMetrics.responseTime > this.thresholds.responseTime) {
|
| 377 |
+
this.triggerAlert({
|
| 378 |
+
type: 'performance',
|
| 379 |
+
severity: 'medium',
|
| 380 |
+
message: `وقت استجابة بطيء: ${currentMetrics.responseTime}ms`,
|
| 381 |
+
timestamp: Date.now()
|
| 382 |
+
});
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
// فحص معدل الأخطاء
|
| 386 |
+
const errorRate = (currentMetrics.errors / currentMetrics.requests) * 100;
|
| 387 |
+
if (errorRate > this.thresholds.errorRate) {
|
| 388 |
+
this.triggerAlert({
|
| 389 |
+
type: 'performance',
|
| 390 |
+
severity: 'high',
|
| 391 |
+
message: `معدل أخطاء عالي: ${errorRate.toFixed(2)}%`,
|
| 392 |
+
timestamp: Date.now()
|
| 393 |
+
});
|
| 394 |
+
}
|
| 395 |
+
|
| 396 |
+
// فحص معدل التهديدات
|
| 397 |
+
const threatRate = this.getThreatRate();
|
| 398 |
+
if (threatRate > this.thresholds.threatRate) {
|
| 399 |
+
this.triggerAlert({
|
| 400 |
+
type: 'security',
|
| 401 |
+
severity: 'critical',
|
| 402 |
+
message: `معدل تهديدات عالي: ${threatRate} تهديد/دقيقة`,
|
| 403 |
+
timestamp: Date.now()
|
| 404 |
+
});
|
| 405 |
+
}
|
| 406 |
+
}
|
| 407 |
+
|
| 408 |
+
/**
|
| 409 |
+
* حساب معدل التهديدات
|
| 410 |
+
* Calculate threat rate
|
| 411 |
+
*/
|
| 412 |
+
getThreatRate() {
|
| 413 |
+
const oneMinuteAgo = Date.now() - 60000;
|
| 414 |
+
const recentThreats = this.alerts.filter(alert =>
|
| 415 |
+
alert.timestamp > oneMinuteAgo && alert.severity === 'critical'
|
| 416 |
+
);
|
| 417 |
+
return recentThreats.length;
|
| 418 |
+
}
|
| 419 |
+
|
| 420 |
+
/**
|
| 421 |
+
* تشغيل التنبيه
|
| 422 |
+
* Trigger alert
|
| 423 |
+
*/
|
| 424 |
+
triggerAlert(alert) {
|
| 425 |
+
const fullAlert = {
|
| 426 |
+
id: this.generateId(),
|
| 427 |
+
...alert,
|
| 428 |
+
timestamp: alert.timestamp || Date.now()
|
| 429 |
+
};
|
| 430 |
+
|
| 431 |
+
this.alerts.push(fullAlert);
|
| 432 |
+
|
| 433 |
+
// الاحتفاظ بآخر 1000 تنبيه فقط
|
| 434 |
+
if (this.alerts.length > 1000) {
|
| 435 |
+
this.alerts = this.alerts.slice(-1000);
|
| 436 |
+
}
|
| 437 |
+
|
| 438 |
+
this.triggerEvent('alertTriggered', fullAlert);
|
| 439 |
+
|
| 440 |
+
// إشعار المستخدم إذا كان متاحاً
|
| 441 |
+
if (Notification.permission === 'granted') {
|
| 442 |
+
new Notification(`تنبيه أمني: ${alert.severity}`, {
|
| 443 |
+
body: alert.message,
|
| 444 |
+
icon: '/favicon.ico'
|
| 445 |
+
});
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
console.log('تنبيه أمني:', fullAlert);
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
/**
|
| 452 |
+
* تنظيف التنبيهات القديمة
|
| 453 |
+
* Cleanup old alerts
|
| 454 |
+
*/
|
| 455 |
+
cleanupOldAlerts() {
|
| 456 |
+
const oneDayAgo = Date.now() - 86400000; // 24 hours
|
| 457 |
+
this.alerts = this.alerts.filter(alert => alert.timestamp > oneDayAgo);
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
/**
|
| 461 |
+
* إعداد قاعدة تنبيه جديدة
|
| 462 |
+
* Setup new alert rule
|
| 463 |
+
*/
|
| 464 |
+
addAlertRule(rule) {
|
| 465 |
+
const alertRule = {
|
| 466 |
+
id: this.generateId(),
|
| 467 |
+
...rule,
|
| 468 |
+
createdAt: Date.now()
|
| 469 |
+
};
|
| 470 |
+
|
| 471 |
+
this.alertRules.push(alertRule);
|
| 472 |
+
this.saveConfig();
|
| 473 |
+
this.triggerEvent('alertRuleAdded', alertRule);
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
/**
|
| 477 |
+
* إزالة قاعدة تنبيه
|
| 478 |
+
* Remove alert rule
|
| 479 |
+
*/
|
| 480 |
+
removeAlertRule(ruleId) {
|
| 481 |
+
const index = this.alertRules.findIndex(rule => rule.id === ruleId);
|
| 482 |
+
if (index !== -1) {
|
| 483 |
+
const removedRule = this.alertRules.splice(index, 1)[0];
|
| 484 |
+
this.saveConfig();
|
| 485 |
+
this.triggerEvent('alertRuleRemoved', removedRule);
|
| 486 |
+
}
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
/**
|
| 490 |
+
* الحصول على التنبيهات
|
| 491 |
+
* Get alerts
|
| 492 |
+
*/
|
| 493 |
+
getAlerts(limit = 50, severity = null) {
|
| 494 |
+
let filteredAlerts = this.alerts;
|
| 495 |
+
|
| 496 |
+
if (severity) {
|
| 497 |
+
filteredAlerts = filteredAlerts.filter(alert => alert.severity === severity);
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
return filteredAlerts
|
| 501 |
+
.sort((a, b) => b.timestamp - a.timestamp)
|
| 502 |
+
.slice(0, limit);
|
| 503 |
+
}
|
| 504 |
+
|
| 505 |
+
/**
|
| 506 |
+
* الحصول على المقاييس
|
| 507 |
+
* Get metrics
|
| 508 |
+
*/
|
| 509 |
+
getMetrics() {
|
| 510 |
+
return {
|
| 511 |
+
...this.metrics,
|
| 512 |
+
uptime: this.isMonitoring ? Date.now() - this.startTime : 0,
|
| 513 |
+
alertCount: this.alerts.length,
|
| 514 |
+
timestamp: Date.now()
|
| 515 |
+
};
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
/**
|
| 519 |
+
* الحصول على الإحصائيات
|
| 520 |
+
* Get statistics
|
| 521 |
+
*/
|
| 522 |
+
getStatistics() {
|
| 523 |
+
const now = Date.now();
|
| 524 |
+
const oneHourAgo = now - 3600000;
|
| 525 |
+
const oneDayAgo = now - 86400000;
|
| 526 |
+
|
| 527 |
+
const recentAlerts = this.alerts.filter(alert => alert.timestamp > oneHourAgo);
|
| 528 |
+
const dailyAlerts = this.alerts.filter(alert => alert.timestamp > oneDayAgo);
|
| 529 |
+
|
| 530 |
+
const severityCounts = this.alerts.reduce((counts, alert) => {
|
| 531 |
+
counts[alert.severity] = (counts[alert.severity] || 0) + 1;
|
| 532 |
+
return counts;
|
| 533 |
+
}, {});
|
| 534 |
+
|
| 535 |
+
const typeCounts = this.alerts.reduce((counts, alert) => {
|
| 536 |
+
counts[alert.type] = (counts[alert.type] || 0) + 1;
|
| 537 |
+
return counts;
|
| 538 |
+
}, {});
|
| 539 |
+
|
| 540 |
+
return {
|
| 541 |
+
totalAlerts: this.alerts.length,
|
| 542 |
+
recentAlerts: recentAlerts.length,
|
| 543 |
+
dailyAlerts: dailyAlerts.length,
|
| 544 |
+
severityCounts,
|
| 545 |
+
typeCounts,
|
| 546 |
+
avgResponseTime: this.metrics.responseTime,
|
| 547 |
+
uptime: this.isMonitoring ? now - this.startTime : 0
|
| 548 |
+
};
|
| 549 |
+
}
|
| 550 |
+
|
| 551 |
+
/**
|
| 552 |
+
* تصدير البيانات
|
| 553 |
+
* Export data
|
| 554 |
+
*/
|
| 555 |
+
exportData(format = 'json') {
|
| 556 |
+
const data = {
|
| 557 |
+
alerts: this.alerts,
|
| 558 |
+
metrics: this.metrics,
|
| 559 |
+
alertRules: this.alertRules,
|
| 560 |
+
statistics: this.getStatistics(),
|
| 561 |
+
exportDate: new Date().toISOString()
|
| 562 |
+
};
|
| 563 |
+
|
| 564 |
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
| 565 |
+
const filename = `security-monitor-${timestamp}.${format}`;
|
| 566 |
+
|
| 567 |
+
if (format === 'json') {
|
| 568 |
+
const dataStr = JSON.stringify(data, null, 2);
|
| 569 |
+
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
| 570 |
+
const url = URL.createObjectURL(dataBlob);
|
| 571 |
+
|
| 572 |
+
const link = document.createElement('a');
|
| 573 |
+
link.href = url;
|
| 574 |
+
link.download = filename;
|
| 575 |
+
link.click();
|
| 576 |
+
|
| 577 |
+
URL.revokeObjectURL(url);
|
| 578 |
+
}
|
| 579 |
+
}
|
| 580 |
+
|
| 581 |
+
/**
|
| 582 |
+
* طلب إذن الإشعارات
|
| 583 |
+
* Request notification permission
|
| 584 |
+
*/
|
| 585 |
+
requestNotificationPermission() {
|
| 586 |
+
if ('Notification' in window) {
|
| 587 |
+
Notification.requestPermission().then(permission => {
|
| 588 |
+
this.triggerEvent('notificationPermissionChanged', { permission });
|
| 589 |
+
});
|
| 590 |
+
}
|
| 591 |
+
}
|
| 592 |
+
|
| 593 |
+
/**
|
| 594 |
+
* حفظ الإعدادات
|
| 595 |
+
* Save configuration
|
| 596 |
+
*/
|
| 597 |
+
saveConfig() {
|
| 598 |
+
const config = {
|
| 599 |
+
thresholds: this.thresholds,
|
| 600 |
+
alertRules: this.alertRules,
|
| 601 |
+
lastSaved: Date.now()
|
| 602 |
+
};
|
| 603 |
+
localStorage.setItem('securityMonitorConfig', JSON.stringify(config));
|
| 604 |
+
}
|
| 605 |
+
|
| 606 |
+
/**
|
| 607 |
+
* تحميل الإعدادات المحفوظة
|
| 608 |
+
* Load saved configuration
|
| 609 |
+
*/
|
| 610 |
+
loadSavedConfig() {
|
| 611 |
+
try {
|
| 612 |
+
const saved = localStorage.getItem('securityMonitorConfig');
|
| 613 |
+
if (saved) {
|
| 614 |
+
const config = JSON.parse(saved);
|
| 615 |
+
this.thresholds = { ...this.thresholds, ...config.thresholds };
|
| 616 |
+
this.alertRules = config.alertRules || [];
|
| 617 |
+
}
|
| 618 |
+
} catch (error) {
|
| 619 |
+
console.error('خطأ في تحميل الإعدادات:', error);
|
| 620 |
+
}
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
/**
|
| 624 |
+
* تهيئة المقاييس
|
| 625 |
+
* Initialize metrics
|
| 626 |
+
*/
|
| 627 |
+
initializeMetrics() {
|
| 628 |
+
this.startTime = Date.now();
|
| 629 |
+
this.lastRequestTime = new Map();
|
| 630 |
+
}
|
| 631 |
+
|
| 632 |
+
/**
|
| 633 |
+
* الحصول على وقت الطلب
|
| 634 |
+
* Get request time
|
| 635 |
+
*/
|
| 636 |
+
getRequestTime(type) {
|
| 637 |
+
return this.lastRequestTime.get(type) || Date.now();
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
/**
|
| 641 |
+
* تسجيل حدث
|
| 642 |
+
* Register event
|
| 643 |
+
*/
|
| 644 |
+
on(eventName, handler) {
|
| 645 |
+
if (!this.eventHandlers.has(eventName)) {
|
| 646 |
+
this.eventHandlers.set(eventName, []);
|
| 647 |
+
}
|
| 648 |
+
this.eventHandlers.get(eventName).push(handler);
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
/**
|
| 652 |
+
* إلغاء تسجيل حدث
|
| 653 |
+
* Unregister event
|
| 654 |
+
*/
|
| 655 |
+
off(eventName, handler) {
|
| 656 |
+
if (this.eventHandlers.has(eventName)) {
|
| 657 |
+
const handlers = this.eventHandlers.get(eventName);
|
| 658 |
+
const index = handlers.indexOf(handler);
|
| 659 |
+
if (index > -1) {
|
| 660 |
+
handlers.splice(index, 1);
|
| 661 |
+
}
|
| 662 |
+
}
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
/**
|
| 666 |
+
* تشغيل حدث
|
| 667 |
+
* Trigger event
|
| 668 |
+
*/
|
| 669 |
+
triggerEvent(eventName, data) {
|
| 670 |
+
if (this.eventHandlers.has(eventName)) {
|
| 671 |
+
this.eventHandlers.get(eventName).forEach(handler => {
|
| 672 |
+
try {
|
| 673 |
+
handler(data);
|
| 674 |
+
} catch (error) {
|
| 675 |
+
console.error('خطأ في معالج الحدث:', error);
|
| 676 |
+
}
|
| 677 |
+
});
|
| 678 |
+
}
|
| 679 |
+
}
|
| 680 |
+
|
| 681 |
+
/**
|
| 682 |
+
* توليد معرف فريد
|
| 683 |
+
* Generate unique ID
|
| 684 |
+
*/
|
| 685 |
+
generateId() {
|
| 686 |
+
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
| 687 |
+
}
|
| 688 |
+
|
| 689 |
+
/**
|
| 690 |
+
* تنظيف الموارد
|
| 691 |
+
* Cleanup resources
|
| 692 |
+
*/
|
| 693 |
+
destroy() {
|
| 694 |
+
this.stopMonitoring();
|
| 695 |
+
|
| 696 |
+
if (this.domObserver) {
|
| 697 |
+
this.domObserver.disconnect();
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
this.eventHandlers.clear();
|
| 701 |
+
this.alerts = [];
|
| 702 |
+
this.metrics = {
|
| 703 |
+
requests: 0,
|
| 704 |
+
blockedRequests: 0,
|
| 705 |
+
threats: 0,
|
| 706 |
+
responseTime: 0,
|
| 707 |
+
errors: 0
|
| 708 |
+
};
|
| 709 |
+
|
| 710 |
+
console.log('تم تنظيف نظام المراقبة الأمنية');
|
| 711 |
+
}
|
| 712 |
+
}
|
| 713 |
+
|
| 714 |
+
// إنشاء مثيل عام للنظام
|
| 715 |
+
const securityMonitor = new SecurityMonitor();
|
| 716 |
+
|
| 717 |
+
// تصدير للاستخدام العام
|
| 718 |
+
window.SecurityMonitor = SecurityMonitor;
|
| 719 |
+
window.securityMonitor = securityMonitor;
|
js/security-dashboard.js
ADDED
|
@@ -0,0 +1,1158 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* لوحة معلومات الأمان الشاملة
|
| 3 |
+
* Comprehensive Security Dashboard
|
| 4 |
+
* Real-time security monitoring and analytics platform
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
class SecurityDashboard {
|
| 8 |
+
constructor() {
|
| 9 |
+
this.data = {
|
| 10 |
+
threats: [],
|
| 11 |
+
metrics: {},
|
| 12 |
+
alerts: [],
|
| 13 |
+
trends: [],
|
| 14 |
+
reports: []
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
this.widgets = new Map();
|
| 18 |
+
this.updateInterval = null;
|
| 19 |
+
this.realTimeMonitor = null;
|
| 20 |
+
this.isRealTimeEnabled = false;
|
| 21 |
+
this.dashboardConfig = this.loadConfig();
|
| 22 |
+
|
| 23 |
+
this.init();
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
/**
|
| 27 |
+
* تهيئة لوحة المعلومات
|
| 28 |
+
* Initialize dashboard
|
| 29 |
+
*/
|
| 30 |
+
init() {
|
| 31 |
+
this.setupRealTimeMonitoring();
|
| 32 |
+
this.initializeWidgets();
|
| 33 |
+
this.loadHistoricalData();
|
| 34 |
+
this.startPeriodicUpdates();
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
/**
|
| 38 |
+
* إعداد المراقبة في الوقت الفعلي
|
| 39 |
+
* Setup real-time monitoring
|
| 40 |
+
*/
|
| 41 |
+
setupRealTimeMonitoring() {
|
| 42 |
+
if (window.securityMonitor) {
|
| 43 |
+
this.realTimeMonitor = window.securityMonitor;
|
| 44 |
+
|
| 45 |
+
// الاستماع لأحداث المراقبة
|
| 46 |
+
this.realTimeMonitor.on('alertTriggered', (alert) => {
|
| 47 |
+
this.addThreat(alert);
|
| 48 |
+
this.updateThreatMetrics();
|
| 49 |
+
});
|
| 50 |
+
|
| 51 |
+
this.realTimeMonitor.on('metricsCollected', (metrics) => {
|
| 52 |
+
this.updateMetrics(metrics);
|
| 53 |
+
});
|
| 54 |
+
}
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
/**
|
| 58 |
+
* تهيئة الأدوات
|
| 59 |
+
* Initialize widgets
|
| 60 |
+
*/
|
| 61 |
+
initializeWidgets() {
|
| 62 |
+
this.widgets.set('threat-overview', new ThreatOverviewWidget());
|
| 63 |
+
this.widgets.set('security-score', new SecurityScoreWidget());
|
| 64 |
+
this.widgets.set('real-time-alerts', new RealTimeAlertsWidget());
|
| 65 |
+
this.widgets.set('threat-trends', new ThreatTrendsWidget());
|
| 66 |
+
this.widgets.set('compliance-status', new ComplianceStatusWidget());
|
| 67 |
+
this.widgets.set('incident-timeline', new IncidentTimelineWidget());
|
| 68 |
+
this.widgets.set('security-policies', new SecurityPoliciesWidget());
|
| 69 |
+
this.widgets.set('performance-metrics', new PerformanceMetricsWidget());
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
/**
|
| 73 |
+
* إضافة تهديد جديد
|
| 74 |
+
* Add new threat
|
| 75 |
+
*/
|
| 76 |
+
addThreat(threatData) {
|
| 77 |
+
const threat = {
|
| 78 |
+
id: this.generateId(),
|
| 79 |
+
...threatData,
|
| 80 |
+
timestamp: threatData.timestamp || Date.now(),
|
| 81 |
+
status: 'new',
|
| 82 |
+
severity: threatData.severity || 'medium',
|
| 83 |
+
type: threatData.type || 'unknown',
|
| 84 |
+
source: threatData.source || 'unknown'
|
| 85 |
+
};
|
| 86 |
+
|
| 87 |
+
this.data.threats.unshift(threat);
|
| 88 |
+
|
| 89 |
+
// الاحتفاظ بآخر 1000 تهديد فقط
|
| 90 |
+
if (this.data.threats.length > 1000) {
|
| 91 |
+
this.data.threats = this.data.threats.slice(0, 1000);
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
this.saveThreatData();
|
| 95 |
+
this.notifyThreatUpdate(threat);
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
/**
|
| 99 |
+
* تحديث المقاييس
|
| 100 |
+
* Update metrics
|
| 101 |
+
*/
|
| 102 |
+
updateMetrics(newMetrics) {
|
| 103 |
+
this.data.metrics = {
|
| 104 |
+
...this.data.metrics,
|
| 105 |
+
...newMetrics,
|
| 106 |
+
lastUpdate: Date.now()
|
| 107 |
+
};
|
| 108 |
+
|
| 109 |
+
this.saveMetricsData();
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
/**
|
| 113 |
+
* الحصول على نظرة عامة على التهديدات
|
| 114 |
+
* Get threat overview
|
| 115 |
+
*/
|
| 116 |
+
getThreatOverview() {
|
| 117 |
+
const now = Date.now();
|
| 118 |
+
const oneHourAgo = now - 3600000;
|
| 119 |
+
const oneDayAgo = now - 86400000;
|
| 120 |
+
const oneWeekAgo = now - 604800000;
|
| 121 |
+
|
| 122 |
+
const recentThreats = this.data.threats.filter(t => t.timestamp > oneHourAgo);
|
| 123 |
+
const dailyThreats = this.data.threats.filter(t => t.timestamp > oneDayAgo);
|
| 124 |
+
const weeklyThreats = this.data.threats.filter(t => t.timestamp > oneWeekAgo);
|
| 125 |
+
|
| 126 |
+
const severityCounts = {
|
| 127 |
+
critical: this.data.threats.filter(t => t.severity === 'critical').length,
|
| 128 |
+
high: this.data.threats.filter(t => t.severity === 'high').length,
|
| 129 |
+
medium: this.data.threats.filter(t => t.severity === 'medium').length,
|
| 130 |
+
low: this.data.threats.filter(t => t.severity === 'low').length,
|
| 131 |
+
info: this.data.threats.filter(t => t.severity === 'info').length
|
| 132 |
+
};
|
| 133 |
+
|
| 134 |
+
const typeCounts = this.data.threats.reduce((counts, threat) => {
|
| 135 |
+
counts[threat.type] = (counts[threat.type] || 0) + 1;
|
| 136 |
+
return counts;
|
| 137 |
+
}, {});
|
| 138 |
+
|
| 139 |
+
return {
|
| 140 |
+
total: this.data.threats.length,
|
| 141 |
+
recent: recentThreats.length,
|
| 142 |
+
daily: dailyThreats.length,
|
| 143 |
+
weekly: weeklyThreats.length,
|
| 144 |
+
severityCounts,
|
| 145 |
+
typeCounts,
|
| 146 |
+
averagePerDay: Math.round(dailyThreats.length / 7),
|
| 147 |
+
trend: this.calculateThreatTrend()
|
| 148 |
+
};
|
| 149 |
+
}
|
| 150 |
+
|
| 151 |
+
/**
|
| 152 |
+
* حساب اتجاه التهديدات
|
| 153 |
+
* Calculate threat trend
|
| 154 |
+
*/
|
| 155 |
+
calculateThreatTrend() {
|
| 156 |
+
const now = Date.now();
|
| 157 |
+
const oneDayAgo = now - 86400000;
|
| 158 |
+
const twoDaysAgo = now - 172800000;
|
| 159 |
+
const threeDaysAgo = now - 259200000;
|
| 160 |
+
|
| 161 |
+
const last24h = this.data.threats.filter(t => t.timestamp > oneDayAgo).length;
|
| 162 |
+
const previous24h = this.data.threats.filter(t =>
|
| 163 |
+
t.timestamp > twoDaysAgo && t.timestamp <= oneDayAgo
|
| 164 |
+
).length;
|
| 165 |
+
const previous48h = this.data.threats.filter(t =>
|
| 166 |
+
t.timestamp > threeDaysAgo && t.timestamp <= twoDaysAgo
|
| 167 |
+
).length;
|
| 168 |
+
|
| 169 |
+
const currentRate = last24h;
|
| 170 |
+
const previousRate = (previous24h + previous48h) / 2;
|
| 171 |
+
|
| 172 |
+
if (currentRate > previousRate * 1.2) {
|
| 173 |
+
return { direction: 'increasing', percentage: Math.round(((currentRate - previousRate) / previousRate) * 100) };
|
| 174 |
+
} else if (currentRate < previousRate * 0.8) {
|
| 175 |
+
return { direction: 'decreasing', percentage: Math.round(((previousRate - currentRate) / previousRate) * 100) };
|
| 176 |
+
} else {
|
| 177 |
+
return { direction: 'stable', percentage: 0 };
|
| 178 |
+
}
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
/**
|
| 182 |
+
* الحصول على درجة الأمان
|
| 183 |
+
* Get security score
|
| 184 |
+
*/
|
| 185 |
+
getSecurityScore() {
|
| 186 |
+
const overview = this.getThreatOverview();
|
| 187 |
+
let score = 100;
|
| 188 |
+
|
| 189 |
+
// خصم النقاط بناءً على التهديدات
|
| 190 |
+
score -= overview.severityCounts.critical * 10;
|
| 191 |
+
score -= overview.severityCounts.high * 5;
|
| 192 |
+
score -= overview.severityCounts.medium * 2;
|
| 193 |
+
score -= overview.severityCounts.low * 1;
|
| 194 |
+
|
| 195 |
+
// خصم النقاط بناءً على العدد الإجمالي
|
| 196 |
+
if (overview.total > 100) score -= 20;
|
| 197 |
+
else if (overview.total > 50) score -= 10;
|
| 198 |
+
else if (overview.total > 20) score -= 5;
|
| 199 |
+
|
| 200 |
+
// ضمان أن النتيجة بين 0 و 100
|
| 201 |
+
score = Math.max(0, Math.min(100, score));
|
| 202 |
+
|
| 203 |
+
// تحديد المستوى
|
| 204 |
+
let level, color, description;
|
| 205 |
+
if (score >= 90) {
|
| 206 |
+
level = 'ممتاز';
|
| 207 |
+
color = '#00C851';
|
| 208 |
+
description = 'مستوى أمان عالي جداً';
|
| 209 |
+
} else if (score >= 75) {
|
| 210 |
+
level = 'جيد';
|
| 211 |
+
color = '#00C851';
|
| 212 |
+
description = 'مستوى أمان جيد';
|
| 213 |
+
} else if (score >= 60) {
|
| 214 |
+
level = 'مقبول';
|
| 215 |
+
color = '#FFBB33';
|
| 216 |
+
description = 'مستوى أمان مقبول';
|
| 217 |
+
} else if (score >= 40) {
|
| 218 |
+
level = 'ضعيف';
|
| 219 |
+
color = '#FF8800';
|
| 220 |
+
description = 'يحتاج تحسين';
|
| 221 |
+
} else {
|
| 222 |
+
level = 'خطر';
|
| 223 |
+
color = '#FF4444';
|
| 224 |
+
description = 'مستوى خطر عالي';
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
return {
|
| 228 |
+
score: Math.round(score),
|
| 229 |
+
level,
|
| 230 |
+
color,
|
| 231 |
+
description,
|
| 232 |
+
lastCalculation: Date.now()
|
| 233 |
+
};
|
| 234 |
+
}
|
| 235 |
+
|
| 236 |
+
/**
|
| 237 |
+
* الحصول على اتجاه التهديدات
|
| 238 |
+
* Get threat trends
|
| 239 |
+
*/
|
| 240 |
+
getThreatTrends(days = 7) {
|
| 241 |
+
const trends = [];
|
| 242 |
+
const now = Date.now();
|
| 243 |
+
|
| 244 |
+
for (let i = days - 1; i >= 0; i--) {
|
| 245 |
+
const dayStart = new Date(now - (i * 86400000));
|
| 246 |
+
dayStart.setHours(0, 0, 0, 0);
|
| 247 |
+
const dayEnd = new Date(dayStart);
|
| 248 |
+
dayEnd.setHours(23, 59, 59, 999);
|
| 249 |
+
|
| 250 |
+
const dayThreats = this.data.threats.filter(t =>
|
| 251 |
+
t.timestamp >= dayStart.getTime() && t.timestamp <= dayEnd.getTime()
|
| 252 |
+
);
|
| 253 |
+
|
| 254 |
+
trends.push({
|
| 255 |
+
date: dayStart.toISOString().split('T')[0],
|
| 256 |
+
total: dayThreats.length,
|
| 257 |
+
critical: dayThreats.filter(t => t.severity === 'critical').length,
|
| 258 |
+
high: dayThreats.filter(t => t.severity === 'high').length,
|
| 259 |
+
medium: dayThreats.filter(t => t.severity === 'medium').length,
|
| 260 |
+
low: dayThreats.filter(t => t.severity === 'low').length,
|
| 261 |
+
info: dayThreats.filter(t => t.severity === 'info').length
|
| 262 |
+
});
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
return trends;
|
| 266 |
+
}
|
| 267 |
+
|
| 268 |
+
/**
|
| 269 |
+
* الحصول على حالة الامتثال
|
| 270 |
+
* Get compliance status
|
| 271 |
+
*/
|
| 272 |
+
getComplianceStatus() {
|
| 273 |
+
const checks = [
|
| 274 |
+
{
|
| 275 |
+
name: 'Content Security Policy',
|
| 276 |
+
status: this.checkCSPCompliance(),
|
| 277 |
+
description: 'فحص وجود وتطبيق CSP',
|
| 278 |
+
severity: 'high'
|
| 279 |
+
},
|
| 280 |
+
{
|
| 281 |
+
name: 'HTTPS Enforcement',
|
| 282 |
+
status: this.checkHTTPSCompliance(),
|
| 283 |
+
description: 'فرض استخدام HTTPS',
|
| 284 |
+
severity: 'critical'
|
| 285 |
+
},
|
| 286 |
+
{
|
| 287 |
+
name: 'X-Frame-Options',
|
| 288 |
+
status: this.checkXFrameOptionsCompliance(),
|
| 289 |
+
description: 'حماية من clickjacking',
|
| 290 |
+
severity: 'medium'
|
| 291 |
+
},
|
| 292 |
+
{
|
| 293 |
+
name: 'X-Content-Type-Options',
|
| 294 |
+
status: this.checkXContentTypeOptionsCompliance(),
|
| 295 |
+
description: 'منع MIME type sniffing',
|
| 296 |
+
severity: 'low'
|
| 297 |
+
},
|
| 298 |
+
{
|
| 299 |
+
name: 'CSRF Protection',
|
| 300 |
+
status: this.checkCSRFCompliance(),
|
| 301 |
+
description: 'حماية من CSRF attacks',
|
| 302 |
+
severity: 'high'
|
| 303 |
+
},
|
| 304 |
+
{
|
| 305 |
+
name: 'Input Validation',
|
| 306 |
+
status: this.checkInputValidationCompliance(),
|
| 307 |
+
description: 'التحقق من المدخلات',
|
| 308 |
+
severity: 'medium'
|
| 309 |
+
}
|
| 310 |
+
];
|
| 311 |
+
|
| 312 |
+
const passed = checks.filter(check => check.status === 'passed').length;
|
| 313 |
+
const failed = checks.filter(check => check.status === 'failed').length;
|
| 314 |
+
const warning = checks.filter(check => check.status === 'warning').length;
|
| 315 |
+
|
| 316 |
+
return {
|
| 317 |
+
checks,
|
| 318 |
+
summary: {
|
| 319 |
+
total: checks.length,
|
| 320 |
+
passed,
|
| 321 |
+
failed,
|
| 322 |
+
warning,
|
| 323 |
+
complianceRate: Math.round((passed / checks.length) * 100)
|
| 324 |
+
}
|
| 325 |
+
};
|
| 326 |
+
}
|
| 327 |
+
|
| 328 |
+
/**
|
| 329 |
+
* فحص امتثال CSP
|
| 330 |
+
* Check CSP compliance
|
| 331 |
+
*/
|
| 332 |
+
checkCSPCompliance() {
|
| 333 |
+
// محاكاة فحص CSP (في التطبيق الحقيقي تحتاج API)
|
| 334 |
+
const hasCSP = this.data.metrics.cspImplemented || false;
|
| 335 |
+
const isStrict = this.data.metrics.cspStrict || false;
|
| 336 |
+
|
| 337 |
+
if (!hasCSP) return 'failed';
|
| 338 |
+
if (!isStrict) return 'warning';
|
| 339 |
+
return 'passed';
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
/**
|
| 343 |
+
* فحص امتثال HTTPS
|
| 344 |
+
* Check HTTPS compliance
|
| 345 |
+
*/
|
| 346 |
+
checkHTTPSCompliance() {
|
| 347 |
+
// محاكاة فحص HTTPS
|
| 348 |
+
const isHTTPS = window.location.protocol === 'https:';
|
| 349 |
+
const hasHSTS = this.data.metrics.hstsImplemented || false;
|
| 350 |
+
|
| 351 |
+
if (!isHTTPS) return 'failed';
|
| 352 |
+
if (!hasHSTS) return 'warning';
|
| 353 |
+
return 'passed';
|
| 354 |
+
}
|
| 355 |
+
|
| 356 |
+
/**
|
| 357 |
+
* فحص امتثال X-Frame-Options
|
| 358 |
+
* Check X-Frame-Options compliance
|
| 359 |
+
*/
|
| 360 |
+
checkXFrameOptionsCompliance() {
|
| 361 |
+
// محاكاة فحص X-Frame-Options
|
| 362 |
+
return this.data.metrics.xFrameOptionsImplemented ? 'passed' : 'warning';
|
| 363 |
+
}
|
| 364 |
+
|
| 365 |
+
/**
|
| 366 |
+
* فحص امتثال X-Content-Type-Options
|
| 367 |
+
* Check X-Content-Type-Options compliance
|
| 368 |
+
*/
|
| 369 |
+
checkXContentTypeOptionsCompliance() {
|
| 370 |
+
// محاكاة فحص X-Content-Type-Options
|
| 371 |
+
return this.data.metrics.xContentTypeOptionsImplemented ? 'passed' : 'warning';
|
| 372 |
+
}
|
| 373 |
+
|
| 374 |
+
/**
|
| 375 |
+
* فحص امتثال CSRF
|
| 376 |
+
* Check CSRF compliance
|
| 377 |
+
*/
|
| 378 |
+
checkCSRFCompliance() {
|
| 379 |
+
// محاكاة فحص CSRF
|
| 380 |
+
return this.data.metrics.csrfProtectionImplemented ? 'passed' : 'failed';
|
| 381 |
+
}
|
| 382 |
+
|
| 383 |
+
/**
|
| 384 |
+
* فحص امتثال التحقق من المدخلات
|
| 385 |
+
* Check input validation compliance
|
| 386 |
+
*/
|
| 387 |
+
checkInputValidationCompliance() {
|
| 388 |
+
// محاكاة فحص التحقق من المدخلات
|
| 389 |
+
return this.data.metrics.inputValidationImplemented ? 'passed' : 'warning';
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
/**
|
| 393 |
+
* الحصول على الجدول الزمني للحوادث
|
| 394 |
+
* Get incident timeline
|
| 395 |
+
*/
|
| 396 |
+
getIncidentTimeline(limit = 50) {
|
| 397 |
+
const incidents = this.data.threats
|
| 398 |
+
.filter(threat => threat.severity === 'critical' || threat.severity === 'high')
|
| 399 |
+
.sort((a, b) => b.timestamp - a.timestamp)
|
| 400 |
+
.slice(0, limit);
|
| 401 |
+
|
| 402 |
+
return incidents.map(incident => ({
|
| 403 |
+
id: incident.id,
|
| 404 |
+
timestamp: incident.timestamp,
|
| 405 |
+
type: incident.type,
|
| 406 |
+
severity: incident.severity,
|
| 407 |
+
description: incident.message || incident.description,
|
| 408 |
+
status: incident.status,
|
| 409 |
+
actions: this.getIncidentActions(incident.id)
|
| 410 |
+
}));
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
/**
|
| 414 |
+
* الحصول على إجراءات الحادث
|
| 415 |
+
* Get incident actions
|
| 416 |
+
*/
|
| 417 |
+
getIncidentActions(incidentId) {
|
| 418 |
+
// في التطبيق الحقيقي، ستحمل من قاعدة البيانات
|
| 419 |
+
return [
|
| 420 |
+
{
|
| 421 |
+
id: this.generateId(),
|
| 422 |
+
timestamp: Date.now(),
|
| 423 |
+
action: 'incident_detected',
|
| 424 |
+
description: 'تم اكتشاف الحادث',
|
| 425 |
+
user: 'النظام'
|
| 426 |
+
},
|
| 427 |
+
{
|
| 428 |
+
id: this.generateId(),
|
| 429 |
+
timestamp: Date.now() + 300000, // 5 minutes later
|
| 430 |
+
action: 'alert_sent',
|
| 431 |
+
description: 'تم إرسال تنبيه',
|
| 432 |
+
user: 'النظام'
|
| 433 |
+
}
|
| 434 |
+
];
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
/**
|
| 438 |
+
* الحصول على سياسات الأمان
|
| 439 |
+
* Get security policies
|
| 440 |
+
*/
|
| 441 |
+
getSecurityPolicies() {
|
| 442 |
+
return [
|
| 443 |
+
{
|
| 444 |
+
id: 'csp-main',
|
| 445 |
+
name: 'سياسة أمان المحتوى الرئيسية',
|
| 446 |
+
status: 'active',
|
| 447 |
+
lastModified: Date.now() - 86400000,
|
| 448 |
+
violations: this.getPolicyViolations('csp'),
|
| 449 |
+
compliance: this.calculatePolicyCompliance('csp')
|
| 450 |
+
},
|
| 451 |
+
{
|
| 452 |
+
id: 'csrf-protection',
|
| 453 |
+
name: 'سياسة حماية CSRF',
|
| 454 |
+
status: 'active',
|
| 455 |
+
lastModified: Date.now() - 172800000,
|
| 456 |
+
violations: this.getPolicyViolations('csrf'),
|
| 457 |
+
compliance: this.calculatePolicyCompliance('csrf')
|
| 458 |
+
},
|
| 459 |
+
{
|
| 460 |
+
id: 'input-validation',
|
| 461 |
+
name: 'سياسة التحقق من المدخلات',
|
| 462 |
+
status: 'active',
|
| 463 |
+
lastModified: Date.now() - 259200000,
|
| 464 |
+
violations: this.getPolicyViolations('input-validation'),
|
| 465 |
+
compliance: this.calculatePolicyCompliance('input-validation')
|
| 466 |
+
}
|
| 467 |
+
];
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
/**
|
| 471 |
+
* الحصول على انتهاكات السياسة
|
| 472 |
+
* Get policy violations
|
| 473 |
+
*/
|
| 474 |
+
getPolicyViolations(policyId) {
|
| 475 |
+
return this.data.threats.filter(threat =>
|
| 476 |
+
threat.policyId === policyId ||
|
| 477 |
+
(policyId === 'csp' && threat.type.includes('csp')) ||
|
| 478 |
+
(policyId === 'csrf' && threat.type.includes('csrf')) ||
|
| 479 |
+
(policyId === 'input-validation' && threat.type.includes('injection'))
|
| 480 |
+
).length;
|
| 481 |
+
}
|
| 482 |
+
|
| 483 |
+
/**
|
| 484 |
+
* حساب امتثال السياسة
|
| 485 |
+
* Calculate policy compliance
|
| 486 |
+
*/
|
| 487 |
+
calculatePolicyCompliance(policyId) {
|
| 488 |
+
const violations = this.getPolicyViolations(policyId);
|
| 489 |
+
const totalRequests = this.data.metrics.requests || 1000;
|
| 490 |
+
const violationRate = (violations / totalRequests) * 100;
|
| 491 |
+
|
| 492 |
+
return Math.max(0, 100 - violationRate);
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
/**
|
| 496 |
+
* الحصول على مقاييس الأداء
|
| 497 |
+
* Get performance metrics
|
| 498 |
+
*/
|
| 499 |
+
getPerformanceMetrics() {
|
| 500 |
+
return {
|
| 501 |
+
responseTime: {
|
| 502 |
+
average: this.data.metrics.averageResponseTime || 250,
|
| 503 |
+
p95: this.data.metrics.p95ResponseTime || 500,
|
| 504 |
+
p99: this.data.metrics.p99ResponseTime || 1000,
|
| 505 |
+
unit: 'ms'
|
| 506 |
+
},
|
| 507 |
+
throughput: {
|
| 508 |
+
current: this.data.metrics.currentThroughput || 100,
|
| 509 |
+
peak: this.data.metrics.peakThroughput || 150,
|
| 510 |
+
unit: 'requests/second'
|
| 511 |
+
},
|
| 512 |
+
errorRate: {
|
| 513 |
+
current: this.data.metrics.errorRate || 0.5,
|
| 514 |
+
threshold: 1.0,
|
| 515 |
+
unit: '%'
|
| 516 |
+
},
|
| 517 |
+
availability: {
|
| 518 |
+
current: this.data.metrics.availability || 99.9,
|
| 519 |
+
target: 99.95,
|
| 520 |
+
unit: '%'
|
| 521 |
+
}
|
| 522 |
+
};
|
| 523 |
+
}
|
| 524 |
+
|
| 525 |
+
/**
|
| 526 |
+
* تفعيل التحديث في الوقت الفعلي
|
| 527 |
+
* Enable real-time updates
|
| 528 |
+
*/
|
| 529 |
+
enableRealTime() {
|
| 530 |
+
if (this.isRealTimeEnabled) return;
|
| 531 |
+
|
| 532 |
+
this.isRealTimeEnabled = true;
|
| 533 |
+
this.updateInterval = setInterval(() => {
|
| 534 |
+
this.updateAllWidgets();
|
| 535 |
+
this.collectCurrentMetrics();
|
| 536 |
+
}, 5000); // تحديث كل 5 ثوان
|
| 537 |
+
|
| 538 |
+
if (this.realTimeMonitor && !this.realTimeMonitor.isMonitoring) {
|
| 539 |
+
this.realTimeMonitor.startMonitoring();
|
| 540 |
+
}
|
| 541 |
+
}
|
| 542 |
+
|
| 543 |
+
/**
|
| 544 |
+
* إلغاء تفعيل التحديث في الوقت الفعلي
|
| 545 |
+
* Disable real-time updates
|
| 546 |
+
*/
|
| 547 |
+
disableRealTime() {
|
| 548 |
+
this.isRealTimeEnabled = false;
|
| 549 |
+
|
| 550 |
+
if (this.updateInterval) {
|
| 551 |
+
clearInterval(this.updateInterval);
|
| 552 |
+
this.updateInterval = null;
|
| 553 |
+
}
|
| 554 |
+
}
|
| 555 |
+
|
| 556 |
+
/**
|
| 557 |
+
* تحديث جميع الأدوات
|
| 558 |
+
* Update all widgets
|
| 559 |
+
*/
|
| 560 |
+
updateAllWidgets() {
|
| 561 |
+
this.widgets.forEach((widget, widgetId) => {
|
| 562 |
+
try {
|
| 563 |
+
const data = this.getWidgetData(widgetId);
|
| 564 |
+
widget.update(data);
|
| 565 |
+
} catch (error) {
|
| 566 |
+
console.error(`خطأ في تحديث widget ${widgetId}:`, error);
|
| 567 |
+
}
|
| 568 |
+
});
|
| 569 |
+
}
|
| 570 |
+
|
| 571 |
+
/**
|
| 572 |
+
* الحصول على بيانات الأداة
|
| 573 |
+
* Get widget data
|
| 574 |
+
*/
|
| 575 |
+
getWidgetData(widgetId) {
|
| 576 |
+
switch (widgetId) {
|
| 577 |
+
case 'threat-overview':
|
| 578 |
+
return this.getThreatOverview();
|
| 579 |
+
case 'security-score':
|
| 580 |
+
return this.getSecurityScore();
|
| 581 |
+
case 'real-time-alerts':
|
| 582 |
+
return this.data.alerts.slice(0, 10);
|
| 583 |
+
case 'threat-trends':
|
| 584 |
+
return this.getThreatTrends();
|
| 585 |
+
case 'compliance-status':
|
| 586 |
+
return this.getComplianceStatus();
|
| 587 |
+
case 'incident-timeline':
|
| 588 |
+
return this.getIncidentTimeline();
|
| 589 |
+
case 'security-policies':
|
| 590 |
+
return this.getSecurityPolicies();
|
| 591 |
+
case 'performance-metrics':
|
| 592 |
+
return this.getPerformanceMetrics();
|
| 593 |
+
default:
|
| 594 |
+
return {};
|
| 595 |
+
}
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
/**
|
| 599 |
+
* جمع المقاييس الحالية
|
| 600 |
+
* Collect current metrics
|
| 601 |
+
*/
|
| 602 |
+
collectCurrentMetrics() {
|
| 603 |
+
if (this.realTimeMonitor) {
|
| 604 |
+
const metrics = this.realTimeMonitor.getMetrics();
|
| 605 |
+
this.updateMetrics(metrics);
|
| 606 |
+
}
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
/**
|
| 610 |
+
* تحميل البيانات التاريخية
|
| 611 |
+
* Load historical data
|
| 612 |
+
*/
|
| 613 |
+
loadHistoricalData() {
|
| 614 |
+
try {
|
| 615 |
+
const saved = localStorage.getItem('securityDashboardData');
|
| 616 |
+
if (saved) {
|
| 617 |
+
const data = JSON.parse(saved);
|
| 618 |
+
this.data = { ...this.data, ...data };
|
| 619 |
+
}
|
| 620 |
+
} catch (error) {
|
| 621 |
+
console.error('خطأ في تحميل البيانات التاريخية:', error);
|
| 622 |
+
}
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
/**
|
| 626 |
+
* حفظ بيانات التهديدات
|
| 627 |
+
* Save threat data
|
| 628 |
+
*/
|
| 629 |
+
saveThreatData() {
|
| 630 |
+
try {
|
| 631 |
+
localStorage.setItem('securityDashboardThreats', JSON.stringify(this.data.threats));
|
| 632 |
+
} catch (error) {
|
| 633 |
+
console.error('خطأ في حفظ بيانات التهديدات:', error);
|
| 634 |
+
}
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
/**
|
| 638 |
+
* حفظ بيانات المقاييس
|
| 639 |
+
* Save metrics data
|
| 640 |
+
*/
|
| 641 |
+
saveMetricsData() {
|
| 642 |
+
try {
|
| 643 |
+
localStorage.setItem('securityDashboardMetrics', JSON.stringify(this.data.metrics));
|
| 644 |
+
} catch (error) {
|
| 645 |
+
console.error('خطأ في حفظ بيانات المقاييس:', error);
|
| 646 |
+
}
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
/**
|
| 650 |
+
* تحميل التكوين
|
| 651 |
+
* Load configuration
|
| 652 |
+
*/
|
| 653 |
+
loadConfig() {
|
| 654 |
+
try {
|
| 655 |
+
const saved = localStorage.getItem('securityDashboardConfig');
|
| 656 |
+
return saved ? JSON.parse(saved) : {
|
| 657 |
+
refreshInterval: 5000,
|
| 658 |
+
enableNotifications: true,
|
| 659 |
+
enableRealTime: true,
|
| 660 |
+
theme: 'dark',
|
| 661 |
+
widgets: Array.from(this.widgets.keys())
|
| 662 |
+
};
|
| 663 |
+
} catch {
|
| 664 |
+
return {
|
| 665 |
+
refreshInterval: 5000,
|
| 666 |
+
enableNotifications: true,
|
| 667 |
+
enableRealTime: true,
|
| 668 |
+
theme: 'dark',
|
| 669 |
+
widgets: Array.from(this.widgets.keys())
|
| 670 |
+
};
|
| 671 |
+
}
|
| 672 |
+
}
|
| 673 |
+
|
| 674 |
+
/**
|
| 675 |
+
* حفظ التكوين
|
| 676 |
+
* Save configuration
|
| 677 |
+
*/
|
| 678 |
+
saveConfig(config) {
|
| 679 |
+
this.dashboardConfig = { ...this.dashboardConfig, ...config };
|
| 680 |
+
localStorage.setItem('securityDashboardConfig', JSON.stringify(this.dashboardConfig));
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
/**
|
| 684 |
+
* بدء التحديثات الدورية
|
| 685 |
+
* Start periodic updates
|
| 686 |
+
*/
|
| 687 |
+
startPeriodicUpdates() {
|
| 688 |
+
if (this.dashboardConfig.enableRealTime) {
|
| 689 |
+
this.enableRealTime();
|
| 690 |
+
}
|
| 691 |
+
}
|
| 692 |
+
|
| 693 |
+
/**
|
| 694 |
+
* إشعار تحديث التهديد
|
| 695 |
+
* Notify threat update
|
| 696 |
+
*/
|
| 697 |
+
notifyThreatUpdate(threat) {
|
| 698 |
+
if (this.dashboardConfig.enableNotifications && Notification.permission === 'granted') {
|
| 699 |
+
const severityColors = {
|
| 700 |
+
critical: '#FF4444',
|
| 701 |
+
high: '#FF8800',
|
| 702 |
+
medium: '#FFAA00',
|
| 703 |
+
low: '#FFDD00',
|
| 704 |
+
info: '#44AA44'
|
| 705 |
+
};
|
| 706 |
+
|
| 707 |
+
new Notification(`تنبيه أمني: ${threat.severity}`, {
|
| 708 |
+
body: threat.message || `تهديد جديد من نوع ${threat.type}`,
|
| 709 |
+
icon: '/favicon.ico',
|
| 710 |
+
badge: '/favicon.ico',
|
| 711 |
+
tag: threat.id,
|
| 712 |
+
requireInteraction: threat.severity === 'critical'
|
| 713 |
+
});
|
| 714 |
+
}
|
| 715 |
+
}
|
| 716 |
+
|
| 717 |
+
/**
|
| 718 |
+
* توليد تقرير
|
| 719 |
+
* Generate report
|
| 720 |
+
*/
|
| 721 |
+
generateReport(type = 'summary', format = 'json') {
|
| 722 |
+
const report = {
|
| 723 |
+
id: this.generateId(),
|
| 724 |
+
type: type,
|
| 725 |
+
generatedAt: new Date().toISOString(),
|
| 726 |
+
period: {
|
| 727 |
+
start: Date.now() - 86400000, // آخر 24 ساعة
|
| 728 |
+
end: Date.now()
|
| 729 |
+
},
|
| 730 |
+
data: {
|
| 731 |
+
threatOverview: this.getThreatOverview(),
|
| 732 |
+
securityScore: this.getSecurityScore(),
|
| 733 |
+
complianceStatus: this.getComplianceStatus(),
|
| 734 |
+
threatTrends: this.getThreatTrends(),
|
| 735 |
+
performanceMetrics: this.getPerformanceMetrics(),
|
| 736 |
+
recentThreats: this.data.threats.slice(0, 20)
|
| 737 |
+
}
|
| 738 |
+
};
|
| 739 |
+
|
| 740 |
+
if (format === 'json') {
|
| 741 |
+
const dataStr = JSON.stringify(report, null, 2);
|
| 742 |
+
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
| 743 |
+
const url = URL.createObjectURL(dataBlob);
|
| 744 |
+
|
| 745 |
+
const link = document.createElement('a');
|
| 746 |
+
link.href = url;
|
| 747 |
+
link.download = `security-report-${type}-${new Date().toISOString().split('T')[0]}.json`;
|
| 748 |
+
link.click();
|
| 749 |
+
|
| 750 |
+
URL.revokeObjectURL(url);
|
| 751 |
+
} else if (format === 'html') {
|
| 752 |
+
const html = this.generateHTMLReport(report);
|
| 753 |
+
const dataBlob = new Blob([html], { type: 'text/html' });
|
| 754 |
+
const url = URL.createObjectURL(dataBlob);
|
| 755 |
+
|
| 756 |
+
const link = document.createElement('a');
|
| 757 |
+
link.href = url;
|
| 758 |
+
link.download = `security-report-${type}-${new Date().toISOString().split('T')[0]}.html`;
|
| 759 |
+
link.click();
|
| 760 |
+
|
| 761 |
+
URL.revokeObjectURL(url);
|
| 762 |
+
}
|
| 763 |
+
|
| 764 |
+
return report;
|
| 765 |
+
}
|
| 766 |
+
|
| 767 |
+
/**
|
| 768 |
+
* توليد تقرير HTML
|
| 769 |
+
* Generate HTML report
|
| 770 |
+
*/
|
| 771 |
+
generateHTMLReport(report) {
|
| 772 |
+
const { data } = report;
|
| 773 |
+
|
| 774 |
+
return `
|
| 775 |
+
<!DOCTYPE html>
|
| 776 |
+
<html dir="rtl" lang="ar">
|
| 777 |
+
<head>
|
| 778 |
+
<meta charset="UTF-8">
|
| 779 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 780 |
+
<title>تقرير الأمان - ${report.type}</title>
|
| 781 |
+
<style>
|
| 782 |
+
body { font-family: 'IBM Plex Sans Arabic', Arial, sans-serif; margin: 20px; background: #0A0A0A; color: #E0E0E0; }
|
| 783 |
+
.header { background: linear-gradient(135deg, #00E0D5, #00B8B8); color: #0A0A0A; padding: 20px; border-radius: 10px; margin-bottom: 20px; }
|
| 784 |
+
.section { background: #1A1A1A; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 1px solid #333; }
|
| 785 |
+
.metric { display: inline-block; background: #2A2A2A; padding: 15px; margin: 10px; border-radius: 8px; min-width: 150px; text-align: center; }
|
| 786 |
+
.metric-value { font-size: 2em; font-weight: bold; color: #00E0D5; }
|
| 787 |
+
.metric-label { color: #888; margin-top: 5px; }
|
| 788 |
+
.severity-critical { color: #FF4444; }
|
| 789 |
+
.severity-high { color: #FF8800; }
|
| 790 |
+
.severity-medium { color: #FFAA00; }
|
| 791 |
+
.severity-low { color: #FFDD00; }
|
| 792 |
+
.severity-info { color: #44AA44; }
|
| 793 |
+
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
|
| 794 |
+
th, td { padding: 12px; text-align: right; border-bottom: 1px solid #333; }
|
| 795 |
+
th { background: #2A2A2A; color: #00E0D5; }
|
| 796 |
+
.status-passed { color: #00C851; }
|
| 797 |
+
.status-failed { color: #FF4444; }
|
| 798 |
+
.status-warning { color: #FFAA00; }
|
| 799 |
+
</style>
|
| 800 |
+
</head>
|
| 801 |
+
<body>
|
| 802 |
+
<div class="header">
|
| 803 |
+
<h1>تقرير الأمان الأمني</h1>
|
| 804 |
+
<p>Security Report - ${report.type}</p>
|
| 805 |
+
<p>تاريخ التوليد: ${new Date(report.generatedAt).toLocaleString('ar-SA')}</p>
|
| 806 |
+
</div>
|
| 807 |
+
|
| 808 |
+
<div class="section">
|
| 809 |
+
<h2>نظرة عامة على التهديدات</h2>
|
| 810 |
+
<div class="metric">
|
| 811 |
+
<div class="metric-value">${data.threatOverview.total}</div>
|
| 812 |
+
<div class="metric-label">إجمالي التهديدات</div>
|
| 813 |
+
</div>
|
| 814 |
+
<div class="metric">
|
| 815 |
+
<div class="metric-value">${data.threatOverview.recent}</div>
|
| 816 |
+
<div class="metric-label">آخر ساعة</div>
|
| 817 |
+
</div>
|
| 818 |
+
<div class="metric">
|
| 819 |
+
<div class="metric-value">${data.threatOverview.daily}</div>
|
| 820 |
+
<div class="metric-label">آخر يوم</div>
|
| 821 |
+
</div>
|
| 822 |
+
</div>
|
| 823 |
+
|
| 824 |
+
<div class="section">
|
| 825 |
+
<h2>درجة الأمان</h2>
|
| 826 |
+
<div class="metric">
|
| 827 |
+
<div class="metric-value" style="color: ${data.securityScore.color};">${data.securityScore.score}</div>
|
| 828 |
+
<div class="metric-label">${data.securityScore.level}</div>
|
| 829 |
+
</div>
|
| 830 |
+
<p>${data.securityScore.description}</p>
|
| 831 |
+
</div>
|
| 832 |
+
|
| 833 |
+
<div class="section">
|
| 834 |
+
<h2>توزيع التهديدات حسب الخطورة</h2>
|
| 835 |
+
<table>
|
| 836 |
+
<tr>
|
| 837 |
+
<th>الخطورة</th>
|
| 838 |
+
<th>العدد</th>
|
| 839 |
+
</tr>
|
| 840 |
+
<tr>
|
| 841 |
+
<td class="severity-critical">حرج</td>
|
| 842 |
+
<td>${data.threatOverview.severityCounts.critical}</td>
|
| 843 |
+
</tr>
|
| 844 |
+
<tr>
|
| 845 |
+
<td class="severity-high">عالي</td>
|
| 846 |
+
<td>${data.threatOverview.severityCounts.high}</td>
|
| 847 |
+
</tr>
|
| 848 |
+
<tr>
|
| 849 |
+
<td class="severity-medium">متوسط</td>
|
| 850 |
+
<td>${data.threatOverview.severityCounts.medium}</td>
|
| 851 |
+
</tr>
|
| 852 |
+
<tr>
|
| 853 |
+
<td class="severity-low">منخفض</td>
|
| 854 |
+
<td>${data.threatOverview.severityCounts.low}</td>
|
| 855 |
+
</tr>
|
| 856 |
+
<tr>
|
| 857 |
+
<td class="severity-info">معلوماتي</td>
|
| 858 |
+
<td>${data.threatOverview.severityCounts.info}</td>
|
| 859 |
+
</tr>
|
| 860 |
+
</table>
|
| 861 |
+
</div>
|
| 862 |
+
|
| 863 |
+
<div class="section">
|
| 864 |
+
<h2>حالة الامتثال</h2>
|
| 865 |
+
<table>
|
| 866 |
+
<tr>
|
| 867 |
+
<th>الفحص</th>
|
| 868 |
+
<th>الحالة</th>
|
| 869 |
+
<th>الوصف</th>
|
| 870 |
+
</tr>
|
| 871 |
+
${data.complianceStatus.checks.map(check => `
|
| 872 |
+
<tr>
|
| 873 |
+
<td>${check.name}</td>
|
| 874 |
+
<td class="status-${check.status}">${check.status === 'passed' ? 'نجح' : check.status === 'failed' ? 'فشل' : 'تحذير'}</td>
|
| 875 |
+
<td>${check.description}</td>
|
| 876 |
+
</tr>
|
| 877 |
+
`).join('')}
|
| 878 |
+
</table>
|
| 879 |
+
</div>
|
| 880 |
+
|
| 881 |
+
<div class="section">
|
| 882 |
+
<h2>التهديدات الحديثة</h2>
|
| 883 |
+
<table>
|
| 884 |
+
<tr>
|
| 885 |
+
<th>الوقت</th>
|
| 886 |
+
<th>النوع</th>
|
| 887 |
+
<th>الخطورة</th>
|
| 888 |
+
<th>الوصف</th>
|
| 889 |
+
</tr>
|
| 890 |
+
${data.recentThreats.map(threat => `
|
| 891 |
+
<tr>
|
| 892 |
+
<td>${new Date(threat.timestamp).toLocaleString('ar-SA')}</td>
|
| 893 |
+
<td>${threat.type}</td>
|
| 894 |
+
<td class="severity-${threat.severity}">${threat.severity}</td>
|
| 895 |
+
<td>${threat.message || threat.description || 'لا يوجد وصف'}</td>
|
| 896 |
+
</tr>
|
| 897 |
+
`).join('')}
|
| 898 |
+
</table>
|
| 899 |
+
</div>
|
| 900 |
+
</body>
|
| 901 |
+
</html>`;
|
| 902 |
+
}
|
| 903 |
+
|
| 904 |
+
/**
|
| 905 |
+
* توليد معرف فريد
|
| 906 |
+
* Generate unique ID
|
| 907 |
+
*/
|
| 908 |
+
generateId() {
|
| 909 |
+
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
| 910 |
+
}
|
| 911 |
+
|
| 912 |
+
/**
|
| 913 |
+
* تنظيف الموارد
|
| 914 |
+
* Cleanup resources
|
| 915 |
+
*/
|
| 916 |
+
destroy() {
|
| 917 |
+
this.disableRealTime();
|
| 918 |
+
this.widgets.clear();
|
| 919 |
+
|
| 920 |
+
if (this.realTimeMonitor) {
|
| 921 |
+
this.realTimeMonitor.destroy();
|
| 922 |
+
}
|
| 923 |
+
}
|
| 924 |
+
}
|
| 925 |
+
|
| 926 |
+
/**
|
| 927 |
+
* أداة نظرة عامة على التهديدات
|
| 928 |
+
* Threat Overview Widget
|
| 929 |
+
*/
|
| 930 |
+
class ThreatOverviewWidget {
|
| 931 |
+
constructor() {
|
| 932 |
+
this.container = null;
|
| 933 |
+
this.chart = null;
|
| 934 |
+
}
|
| 935 |
+
|
| 936 |
+
mount(container) {
|
| 937 |
+
this.container = container;
|
| 938 |
+
this.render();
|
| 939 |
+
}
|
| 940 |
+
|
| 941 |
+
update(data) {
|
| 942 |
+
if (!this.container) return;
|
| 943 |
+
|
| 944 |
+
this.updateThreatCounts(data);
|
| 945 |
+
this.updateCharts(data);
|
| 946 |
+
}
|
| 947 |
+
|
| 948 |
+
render() {
|
| 949 |
+
if (!this.container) return;
|
| 950 |
+
|
| 951 |
+
this.container.innerHTML = `
|
| 952 |
+
<div class="widget-header">
|
| 953 |
+
<h3>نظرة عامة على التهديدات</h3>
|
| 954 |
+
<div class="widget-controls">
|
| 955 |
+
<button class="refresh-btn" onclick="dashboard.updateAllWidgets()">تحديث</button>
|
| 956 |
+
</div>
|
| 957 |
+
</div>
|
| 958 |
+
<div class="threat-overview-content">
|
| 959 |
+
<div class="threat-stats">
|
| 960 |
+
<div class="stat-card">
|
| 961 |
+
<div class="stat-value">0</div>
|
| 962 |
+
<div class="stat-label">إجمالي التهديدات</div>
|
| 963 |
+
</div>
|
| 964 |
+
<div class="stat-card">
|
| 965 |
+
<div class="stat-value">0</div>
|
| 966 |
+
<div class="stat-label">آخر ساعة</div>
|
| 967 |
+
</div>
|
| 968 |
+
<div class="stat-card">
|
| 969 |
+
<div class="stat-value">0</div>
|
| 970 |
+
<div class="stat-label">آخر يوم</div>
|
| 971 |
+
</div>
|
| 972 |
+
</div>
|
| 973 |
+
<div class="severity-breakdown">
|
| 974 |
+
<h4>توزيع التهديدات حسب الخطورة</h4>
|
| 975 |
+
<div class="severity-chart">
|
| 976 |
+
<canvas id="severityChart" width="300" height="200"></canvas>
|
| 977 |
+
</div>
|
| 978 |
+
</div>
|
| 979 |
+
</div>
|
| 980 |
+
`;
|
| 981 |
+
}
|
| 982 |
+
|
| 983 |
+
updateThreatCounts(data) {
|
| 984 |
+
const statCards = this.container.querySelectorAll('.stat-card .stat-value');
|
| 985 |
+
if (statCards.length >= 3) {
|
| 986 |
+
statCards[0].textContent = data.total || 0;
|
| 987 |
+
statCards[1].textContent = data.recent || 0;
|
| 988 |
+
statCards[2].textContent = data.daily || 0;
|
| 989 |
+
}
|
| 990 |
+
}
|
| 991 |
+
|
| 992 |
+
updateCharts(data) {
|
| 993 |
+
const canvas = this.container.querySelector('#severityChart');
|
| 994 |
+
if (!canvas) return;
|
| 995 |
+
|
| 996 |
+
const ctx = canvas.getContext('2d');
|
| 997 |
+
const severityData = data.severityCounts || {};
|
| 998 |
+
|
| 999 |
+
// رسم مخطط دائري بسيط
|
| 1000 |
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 1001 |
+
|
| 1002 |
+
const centerX = canvas.width / 2;
|
| 1003 |
+
const centerY = canvas.height / 2;
|
| 1004 |
+
const radius = Math.min(centerX, centerY) - 20;
|
| 1005 |
+
|
| 1006 |
+
const colors = {
|
| 1007 |
+
critical: '#FF4444',
|
| 1008 |
+
high: '#FF8800',
|
| 1009 |
+
medium: '#FFAA00',
|
| 1010 |
+
low: '#FFDD00',
|
| 1011 |
+
info: '#44AA44'
|
| 1012 |
+
};
|
| 1013 |
+
|
| 1014 |
+
let currentAngle = 0;
|
| 1015 |
+
const total = Object.values(severityData).reduce((sum, count) => sum + count, 0);
|
| 1016 |
+
|
| 1017 |
+
Object.entries(severityData).forEach(([severity, count]) => {
|
| 1018 |
+
if (count > 0) {
|
| 1019 |
+
const sliceAngle = (count / total) * 2 * Math.PI;
|
| 1020 |
+
|
| 1021 |
+
ctx.beginPath();
|
| 1022 |
+
ctx.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
|
| 1023 |
+
ctx.lineTo(centerX, centerY);
|
| 1024 |
+
ctx.fillStyle = colors[severity] || '#666';
|
| 1025 |
+
ctx.fill();
|
| 1026 |
+
|
| 1027 |
+
currentAngle += sliceAngle;
|
| 1028 |
+
}
|
| 1029 |
+
});
|
| 1030 |
+
|
| 1031 |
+
// إضافة وسيلة الإيضاح
|
| 1032 |
+
const legendY = canvas.height - 60;
|
| 1033 |
+
let legendX = 10;
|
| 1034 |
+
|
| 1035 |
+
Object.entries(severityData).forEach(([severity, count]) => {
|
| 1036 |
+
if (count > 0) {
|
| 1037 |
+
ctx.fillStyle = colors[severity] || '#666';
|
| 1038 |
+
ctx.fillRect(legendX, legendY, 15, 15);
|
| 1039 |
+
ctx.fillStyle = '#E0E0E0';
|
| 1040 |
+
ctx.font = '12px Arial';
|
| 1041 |
+
ctx.fillText(`${severity}: ${count}`, legendX + 20, legendY + 12);
|
| 1042 |
+
legendX += 80;
|
| 1043 |
+
}
|
| 1044 |
+
});
|
| 1045 |
+
}
|
| 1046 |
+
}
|
| 1047 |
+
|
| 1048 |
+
/**
|
| 1049 |
+
* أداة درجة الأمان
|
| 1050 |
+
* Security Score Widget
|
| 1051 |
+
*/
|
| 1052 |
+
class SecurityScoreWidget {
|
| 1053 |
+
constructor() {
|
| 1054 |
+
this.container = null;
|
| 1055 |
+
}
|
| 1056 |
+
|
| 1057 |
+
mount(container) {
|
| 1058 |
+
this.container = container;
|
| 1059 |
+
this.render();
|
| 1060 |
+
}
|
| 1061 |
+
|
| 1062 |
+
update(data) {
|
| 1063 |
+
if (!this.container) return;
|
| 1064 |
+
|
| 1065 |
+
const scoreElement = this.container.querySelector('.security-score-value');
|
| 1066 |
+
const levelElement = this.container.querySelector('.security-score-level');
|
| 1067 |
+
const descriptionElement = this.container.querySelector('.security-score-description');
|
| 1068 |
+
|
| 1069 |
+
if (scoreElement) {
|
| 1070 |
+
scoreElement.textContent = data.score || 0;
|
| 1071 |
+
scoreElement.style.color = data.color || '#00E0D5';
|
| 1072 |
+
}
|
| 1073 |
+
|
| 1074 |
+
if (levelElement) {
|
| 1075 |
+
levelElement.textContent = data.level || 'غير معروف';
|
| 1076 |
+
levelElement.style.color = data.color || '#00E0D5';
|
| 1077 |
+
}
|
| 1078 |
+
|
| 1079 |
+
if (descriptionElement) {
|
| 1080 |
+
descriptionElement.textContent = data.description || '';
|
| 1081 |
+
}
|
| 1082 |
+
}
|
| 1083 |
+
|
| 1084 |
+
render() {
|
| 1085 |
+
if (!this.container) return;
|
| 1086 |
+
|
| 1087 |
+
this.container.innerHTML = `
|
| 1088 |
+
<div class="widget-header">
|
| 1089 |
+
<h3>درجة الأمان</h3>
|
| 1090 |
+
</div>
|
| 1091 |
+
<div class="security-score-content">
|
| 1092 |
+
<div class="score-display">
|
| 1093 |
+
<div class="security-score-value">0</div>
|
| 1094 |
+
<div class="security-score-level">غير معروف</div>
|
| 1095 |
+
</div>
|
| 1096 |
+
<div class="security-score-description">
|
| 1097 |
+
يتم حساب درجة الأمان بناءً على التهديدات المكتشفة والامتثال للمعايير الأمنية
|
| 1098 |
+
</div>
|
| 1099 |
+
</div>
|
| 1100 |
+
`;
|
| 1101 |
+
}
|
| 1102 |
+
}
|
| 1103 |
+
|
| 1104 |
+
/**
|
| 1105 |
+
* أدوات أخرى مشابهة...
|
| 1106 |
+
* Similar other widgets...
|
| 1107 |
+
*/
|
| 1108 |
+
class RealTimeAlertsWidget {
|
| 1109 |
+
constructor() {
|
| 1110 |
+
this.container = null;
|
| 1111 |
+
}
|
| 1112 |
+
|
| 1113 |
+
mount(container) {
|
| 1114 |
+
this.container = container;
|
| 1115 |
+
this.render();
|
| 1116 |
+
}
|
| 1117 |
+
|
| 1118 |
+
update(data) {
|
| 1119 |
+
if (!this.container) return;
|
| 1120 |
+
|
| 1121 |
+
const alertsList = this.container.querySelector('.alerts-list');
|
| 1122 |
+
if (alertsList) {
|
| 1123 |
+
alertsList.innerHTML = data.map(alert => `
|
| 1124 |
+
<div class="alert-item severity-${alert.severity}">
|
| 1125 |
+
<div class="alert-time">${new Date(alert.timestamp).toLocaleTimeString('ar-SA')}</div>
|
| 1126 |
+
<div class="alert-message">${alert.message || alert.description}</div>
|
| 1127 |
+
<div class="alert-severity">${alert.severity}</div>
|
| 1128 |
+
</div>
|
| 1129 |
+
`).join('');
|
| 1130 |
+
}
|
| 1131 |
+
}
|
| 1132 |
+
|
| 1133 |
+
render() {
|
| 1134 |
+
if (!this.container) return;
|
| 1135 |
+
|
| 1136 |
+
this.container.innerHTML = `
|
| 1137 |
+
<div class="widget-header">
|
| 1138 |
+
<h3>التنبيهات في الوقت الفعلي</h3>
|
| 1139 |
+
</div>
|
| 1140 |
+
<div class="alerts-list">
|
| 1141 |
+
<div class="no-alerts">لا توجد تنبيهات جديدة</div>
|
| 1142 |
+
</div>
|
| 1143 |
+
`;
|
| 1144 |
+
}
|
| 1145 |
+
}
|
| 1146 |
+
|
| 1147 |
+
// أدوات إضافية...
|
| 1148 |
+
class ThreatTrendsWidget {}
|
| 1149 |
+
class ComplianceStatusWidget {}
|
| 1150 |
+
class IncidentTimelineWidget {}
|
| 1151 |
+
class SecurityPoliciesWidget {}
|
| 1152 |
+
class PerformanceMetricsWidget {}
|
| 1153 |
+
|
| 1154 |
+
// تصدير الكلاسات للاستخدام
|
| 1155 |
+
window.SecurityDashboard = SecurityDashboard;
|
| 1156 |
+
window.ThreatOverviewWidget = ThreatOverviewWidget;
|
| 1157 |
+
window.SecurityScoreWidget = SecurityScoreWidget;
|
| 1158 |
+
window.RealTimeAlertsWidget = RealTimeAlertsWidget;
|
js/security-training.js
ADDED
|
@@ -0,0 +1,1110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* أدوات التوعية التفاعلية
|
| 3 |
+
* Interactive Security Training Tools
|
| 4 |
+
* Comprehensive security education and training platform
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
class SecurityTraining {
|
| 8 |
+
constructor() {
|
| 9 |
+
this.modules = this.initializeTrainingModules();
|
| 10 |
+
this.currentModule = null;
|
| 11 |
+
this.currentLesson = 0;
|
| 12 |
+
this.progress = this.loadProgress();
|
| 13 |
+
this.achievements = this.loadAchievements();
|
| 14 |
+
this.quizResults = this.loadQuizResults();
|
| 15 |
+
this.scenarios = this.initializeScenarios();
|
| 16 |
+
this.isInitialized = false;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
/**
|
| 20 |
+
* تهيئة وحدات التدريب
|
| 21 |
+
* Initialize training modules
|
| 22 |
+
*/
|
| 23 |
+
initializeTrainingModules() {
|
| 24 |
+
return {
|
| 25 |
+
fundamentals: {
|
| 26 |
+
id: 'fundamentals',
|
| 27 |
+
title: 'أساسيات أمان الويب',
|
| 28 |
+
description: 'تعلم المفاهيم الأساسية لأمان الويب',
|
| 29 |
+
difficulty: 'مبتدئ',
|
| 30 |
+
estimatedTime: '30 دقيقة',
|
| 31 |
+
lessons: [
|
| 32 |
+
{
|
| 33 |
+
id: 'intro',
|
| 34 |
+
title: 'مقدمة في أمان الويب',
|
| 35 |
+
content: `
|
| 36 |
+
<h2>مرحباً بك في دورة أساسيات أمان الويب</h2>
|
| 37 |
+
<p>أمان الويب هو مجموعة من التقنيات والممارسات التي تهدف إلى حماية المواقع والتطبيقات من التهديدات المختلفة.</p>
|
| 38 |
+
|
| 39 |
+
<h3>لماذا أمان الويب مهم؟</h3>
|
| 40 |
+
<ul>
|
| 41 |
+
<li><strong>حماية البيانات:</strong> حماية معلومات المستخدمين الحساسة</li>
|
| 42 |
+
<li><strong>منع الهجمات:</strong> تجنب الهجمات مثل XSS و SQL Injection</li>
|
| 43 |
+
<li><strong>الثقة:</strong> بناء ثقة المستخدمين في تطبيقك</li>
|
| 44 |
+
<li><strong>الامتثال:</strong> الالتزام بالقوانين واللوائح</li>
|
| 45 |
+
</ul>
|
| 46 |
+
|
| 47 |
+
<div class="info-box">
|
| 48 |
+
<h4>إحصائية مهمة</h4>
|
| 49 |
+
<p>وفقاً للإحصائيات، <strong>43%</strong> من الشركات الصغيرة والمتوسطة تعرضت لهجمات سيبرانية في العام الماضي.</p>
|
| 50 |
+
</div>
|
| 51 |
+
|
| 52 |
+
<h3>أهم التهديدات الأمنية</h3>
|
| 53 |
+
<div class="threat-grid">
|
| 54 |
+
<div class="threat-card">
|
| 55 |
+
<h4>Cross-Site Scripting (XSS)</h4>
|
| 56 |
+
<p>حقن أكواد ضارة في صفحات الويب</p>
|
| 57 |
+
</div>
|
| 58 |
+
<div class="threat-card">
|
| 59 |
+
<h4>SQL Injection</h4>
|
| 60 |
+
<p>حقن استعلامات ضارة في قاعدة البيانات</p>
|
| 61 |
+
</div>
|
| 62 |
+
<div class="threat-card">
|
| 63 |
+
<h4>Cross-Site Request Forgery (CSRF)</h4>
|
| 64 |
+
<p>توليد طلبات غير مرغوب فيها من المستخدمين</p>
|
| 65 |
+
</div>
|
| 66 |
+
<div class="threat-card">
|
| 67 |
+
<h4>Clickjacking</h4>
|
| 68 |
+
<p>خداع المستخدمين للنقر على عناصر مخفية</p>
|
| 69 |
+
</div>
|
| 70 |
+
</div>
|
| 71 |
+
`,
|
| 72 |
+
quiz: {
|
| 73 |
+
question: 'ما هو الهدف الرئيسي لأمان الويب؟',
|
| 74 |
+
options: [
|
| 75 |
+
'تسريع الموقع',
|
| 76 |
+
'حماية البيانات والمستخدمين',
|
| 77 |
+
'تحسين SEO',
|
| 78 |
+
'تقليل حجم الملفات'
|
| 79 |
+
],
|
| 80 |
+
correct: 1,
|
| 81 |
+
explanation: 'الهدف الرئيسي لأمان الويب هو حماية البيانات والمستخدمين من التهديدات والهجمات المختلفة.'
|
| 82 |
+
}
|
| 83 |
+
},
|
| 84 |
+
{
|
| 85 |
+
id: 'http-basics',
|
| 86 |
+
title: 'أساسيات HTTP وأمانه',
|
| 87 |
+
content: `
|
| 88 |
+
<h2>أساسيات HTTP وأمانه</h2>
|
| 89 |
+
<p>HTTP هو البروتوكول الأساسي لنقل البيانات في الويب، وفهمه ضروري لفهم أمان الويب.</p>
|
| 90 |
+
|
| 91 |
+
<h3>مكونات الطلب (Request)</h3>
|
| 92 |
+
<div class="code-example">
|
| 93 |
+
<div class="code-header">
|
| 94 |
+
<span>HTTP Request</span>
|
| 95 |
+
<button class="copy-btn" onclick="navigator.clipboard.writeText(this.parentElement.nextElementSibling.textContent)">نسخ</button>
|
| 96 |
+
</div>
|
| 97 |
+
<pre><code>GET /api/users HTTP/1.1
|
| 98 |
+
Host: example.com
|
| 99 |
+
User-Agent: Mozilla/5.0
|
| 100 |
+
Accept: application/json
|
| 101 |
+
Authorization: Bearer abc123...</code></pre>
|
| 102 |
+
</div>
|
| 103 |
+
|
| 104 |
+
<h3>مكونات الاستجابة (Response)</h3>
|
| 105 |
+
<div class="code-example">
|
| 106 |
+
<div class="code-header">
|
| 107 |
+
<span>HTTP Response</span>
|
| 108 |
+
<button class="copy-btn" onclick="navigator.clipboard.writeText(this.parentElement.nextElementSibling.textContent)">نسخ</button>
|
| 109 |
+
</div>
|
| 110 |
+
<pre><code>HTTP/1.1 200 OK
|
| 111 |
+
Content-Type: application/json
|
| 112 |
+
Content-Length: 123
|
| 113 |
+
Cache-Control: no-cache
|
| 114 |
+
|
| 115 |
+
{"users": [...], "status": "success"}</code></pre>
|
| 116 |
+
</div>
|
| 117 |
+
|
| 118 |
+
<h3>رؤوس الأمان المهمة</h3>
|
| 119 |
+
="security- <div classheaders">
|
| 120 |
+
<div class="header-item">
|
| 121 |
+
<strong>Content-Security-Policy</strong>
|
| 122 |
+
<p>يحدد مصادر المحتوى المسموحة</p>
|
| 123 |
+
</div>
|
| 124 |
+
<div class="header-item">
|
| 125 |
+
<strong>X-Frame-Options</strong>
|
| 126 |
+
<p>منع تضمين الموقع في إطارات</p>
|
| 127 |
+
</div>
|
| 128 |
+
<div class="header-item">
|
| 129 |
+
<strong>X-XSS-Protection</strong>
|
| 130 |
+
<p>تفعيل حماية XSS في المتصفح</p>
|
| 131 |
+
</div>
|
| 132 |
+
<div class="header-item">
|
| 133 |
+
<strong>Strict-Transport-Security</strong>
|
| 134 |
+
<p>فرض استخدام HTTPS</p>
|
| 135 |
+
</div>
|
| 136 |
+
</div>
|
| 137 |
+
|
| 138 |
+
<div class="interactive-demo">
|
| 139 |
+
<h4>تجربة تفاعلية: رؤوس HTTP</h4>
|
| 140 |
+
<p>انقر على الرؤوس لفهم تأثيرها:</p>
|
| 141 |
+
<div class="headers-demo">
|
| 142 |
+
<button class="header-btn" onclick="showHeaderInfo('CSP')">Content-Security-Policy</button>
|
| 143 |
+
<button class="header-btn" onclick="showHeaderInfo('XFO')">X-Frame-Options</button>
|
| 144 |
+
<button class="header-btn" onclick="showHeaderInfo('XSS')">X-XSS-Protection</button>
|
| 145 |
+
<button class="header-btn" onclick="showHeaderInfo('HSTS')">Strict-Transport-Security</button>
|
| 146 |
+
</div>
|
| 147 |
+
<div id="header-info" class="header-info"></div>
|
| 148 |
+
</div>
|
| 149 |
+
`,
|
| 150 |
+
quiz: {
|
| 151 |
+
question: 'ما هو الغرض من Content-Security-Policy؟',
|
| 152 |
+
options: [
|
| 153 |
+
'تسريع تحميل الصفحات',
|
| 154 |
+
'تحديد مصادر المحتوى المسموحة',
|
| 155 |
+
'ضغط البيانات',
|
| 156 |
+
'تشفير البيانات'
|
| 157 |
+
],
|
| 158 |
+
correct: 1,
|
| 159 |
+
explanation: 'Content-Security-Policy يحدد المصادر المسموحة للمحتوى مثل السكريبت والأنماط والصور.'
|
| 160 |
+
}
|
| 161 |
+
},
|
| 162 |
+
{
|
| 163 |
+
id: 'csp-basics',
|
| 164 |
+
title: 'أساسيات سياسة أمان المحتوى',
|
| 165 |
+
content: `
|
| 166 |
+
<h2>سياسة أمان المحتوى (CSP)</h2>
|
| 167 |
+
<p>CSP هي طبقة أمان قوية تساعد في منع هجمات XSS وتوفر تحكماً دقيقاً في مصادر المحتوى.</p>
|
| 168 |
+
|
| 169 |
+
<h3>كيف تعمل CSP؟</h3>
|
| 170 |
+
<p>يعمل CSP كحارس أمني يفحص كل عنصر قبل تحميله في المتصفح. إذا لم يطابق السياسة، يتم منعه.</p>
|
| 171 |
+
|
| 172 |
+
<div class="workflow-diagram">
|
| 173 |
+
<div class="workflow-step">
|
| 174 |
+
="step-number"> <div class1</div>
|
| 175 |
+
<div class="step-content">المتصفح يطلب مورد</div>
|
| 176 |
+
</div>
|
| 177 |
+
<div class="workflow-arrow">→</div>
|
| 178 |
+
<div class="workflow-step">
|
| 179 |
+
<div class="step-number">2</div>
|
| 180 |
+
<div class="step-content">فحص CSP</div>
|
| 181 |
+
</div>
|
| 182 |
+
<div class="workflow-arrow">→</div>
|
| 183 |
+
<div class="workflow-step">
|
| 184 |
+
<div class="step-number">3</div>
|
| 185 |
+
<div class="step-content">السماح/المنع</div>
|
| 186 |
+
</div>
|
| 187 |
+
<div class="workflow-arrow">→</div>
|
| 188 |
+
<div class="workflow-step">
|
| 189 |
+
<div class="step-number">4</div>
|
| 190 |
+
<div class="step-content">التحميل</div>
|
| 191 |
+
</div>
|
| 192 |
+
</div>
|
| 193 |
+
|
| 194 |
+
<h3>أمثلة على السياسات</h3>
|
| 195 |
+
|
| 196 |
+
<h4>سياسة صارمة</h4>
|
| 197 |
+
<div class="code-example">
|
| 198 |
+
<div class="code-header">
|
| 199 |
+
<span>Strict CSP</span>
|
| 200 |
+
<button class="copy-btn">نسخ</button>
|
| 201 |
+
</div>
|
| 202 |
+
<pre><code>default-src 'none';
|
| 203 |
+
script-src 'self';
|
| 204 |
+
style-src 'self';
|
| 205 |
+
img-src 'self' data:;
|
| 206 |
+
font-src 'self';
|
| 207 |
+
connect-src 'self';
|
| 208 |
+
frame-ancestors 'none';
|
| 209 |
+
base-uri 'self';
|
| 210 |
+
form-action 'self';</code></pre>
|
| 211 |
+
</div>
|
| 212 |
+
|
| 213 |
+
<h4>سياسة متوسطة</h4>
|
| 214 |
+
<div class="code-example">
|
| 215 |
+
<div class="code-header">
|
| 216 |
+
<span>Moderate CSP</span>
|
| 217 |
+
<button class="copy-btn">نسخ</button>
|
| 218 |
+
</div>
|
| 219 |
+
<pre><code>default-src 'self';
|
| 220 |
+
script-src 'self' 'unsafe-inline';
|
| 221 |
+
style-src 'self' 'unsafe-inline';
|
| 222 |
+
img-src 'self' data: https:;
|
| 223 |
+
font-src 'self' https://fonts.googleapis.com;
|
| 224 |
+
connect-src 'self';
|
| 225 |
+
frame-ancestors 'none';
|
| 226 |
+
base-uri 'self';
|
| 227 |
+
form-action 'self';</code></pre>
|
| 228 |
+
</div>
|
| 229 |
+
|
| 230 |
+
<h3>الأوامر الأساسية</h3>
|
| 231 |
+
<div class="directives-table">
|
| 232 |
+
<div class="directive-row header">
|
| 233 |
+
<div>الأمر</div>
|
| 234 |
+
<div>الغرض</div>
|
| 235 |
+
<div>مثال</div>
|
| 236 |
+
</div>
|
| 237 |
+
<div class="directive-row">
|
| 238 |
+
<div><code>default-src</code></div>
|
| 239 |
+
<div>مصادر افتراضية</div>
|
| 240 |
+
<div><code>'self' https:</code></div>
|
| 241 |
+
</div>
|
| 242 |
+
<div class="directive-row">
|
| 243 |
+
<div><code>script-src</code></div>
|
| 244 |
+
<div>مصادر السكريبت</div>
|
| 245 |
+
<div><code>'self' 'unsafe-inline'</code></div>
|
| 246 |
+
</div>
|
| 247 |
+
<div class="directive-row">
|
| 248 |
+
<div><code>style-src</code></div>
|
| 249 |
+
<div>مصادر الأنماط</div>
|
| 250 |
+
<div><code>'self' 'unsafe-inline'</code></div>
|
| 251 |
+
</div>
|
| 252 |
+
<div class="directive-row">
|
| 253 |
+
<div><code>img-src</code></div>
|
| 254 |
+
<div>مصادر الصور</div>
|
| 255 |
+
<div><code>'self' data: https:</code></div>
|
| 256 |
+
</div>
|
| 257 |
+
<div class="directive-row">
|
| 258 |
+
<div><code>frame-ancestors</code></div>
|
| 259 |
+
<div>المواقع التي يمكن تضمينها فيها</div>
|
| 260 |
+
<div><code>'none'</code></div>
|
| 261 |
+
</div>
|
| 262 |
+
</div>
|
| 263 |
+
|
| 264 |
+
<div class="csp-builder-demo">
|
| 265 |
+
<h4>مولد CSP تفاعلي</h4>
|
| 266 |
+
<p>اختر الإعدادات لبناء سي��سة CSP مخصصة:</p>
|
| 267 |
+
<div class="builder-controls">
|
| 268 |
+
<div class="control-group">
|
| 269 |
+
<label>السكريبت:</label>
|
| 270 |
+
<select id="script-src">
|
| 271 |
+
<option value="'self'">النفس فقط</option>
|
| 272 |
+
<option value="'self' 'unsafe-inline'">النفس + المضمنة</option>
|
| 273 |
+
<option value="'self' 'unsafe-eval'">النفس + eval()</option>
|
| 274 |
+
<option value="'self' https://cdn.jsdelivr.net">النفس + CDN</option>
|
| 275 |
+
</select>
|
| 276 |
+
</div>
|
| 277 |
+
<div class="control-group">
|
| 278 |
+
<label>الأنماط:</label>
|
| 279 |
+
<select id="style-src">
|
| 280 |
+
<option value="'self'">النفس فقط</option>
|
| 281 |
+
<option value="'self' 'unsafe-inline'">النفس + المضمنة</option>
|
| 282 |
+
<option value="'self' https://fonts.googleapis.com">النفس + Google Fonts</option>
|
| 283 |
+
</select>
|
| 284 |
+
</div>
|
| 285 |
+
<div class="control-group">
|
| 286 |
+
<label>الصور:</label>
|
| 287 |
+
<select id="img-src">
|
| 288 |
+
<option value="'self'">النفس فقط</option>
|
| 289 |
+
<option value="'self' data:">النفس + data URLs</option>
|
| 290 |
+
<option value="'self' data: https:">النفس + جميع البروتوكولات</option>
|
| 291 |
+
</select>
|
| 292 |
+
</div>
|
| 293 |
+
<div class="control-group">
|
| 294 |
+
<label>الإطارات:</label>
|
| 295 |
+
<select id="frame-ancestors">
|
| 296 |
+
<option value="'none'">منع الكل</option>
|
| 297 |
+
<option value="'self'">النفس فقط</option>
|
| 298 |
+
<option value="'self' https://partner.com">النفس + شريك</option>
|
| 299 |
+
</select>
|
| 300 |
+
</div>
|
| 301 |
+
</div>
|
| 302 |
+
<div class="csp-output">
|
| 303 |
+
<h5>سياسة CSP المولدة:</h5>
|
| 304 |
+
<div class="code-output">
|
| 305 |
+
<code id="generated-csp">default-src 'self';</code>
|
| 306 |
+
</div>
|
| 307 |
+
</div>
|
| 308 |
+
</div>
|
| 309 |
+
`,
|
| 310 |
+
quiz: {
|
| 311 |
+
question: 'أي من الأوامر التالية يمنع تضمين الموقع في إطارات خارجية؟',
|
| 312 |
+
options: [
|
| 313 |
+
'script-src',
|
| 314 |
+
'frame-ancestors',
|
| 315 |
+
'default-src',
|
| 316 |
+
'style-src'
|
| 317 |
+
],
|
| 318 |
+
correct: 1,
|
| 319 |
+
explanation: 'frame-ancestors يحدد المواقع التي يُسمح لها بتضمين موقعك في iframe.'
|
| 320 |
+
}
|
| 321 |
+
}
|
| 322 |
+
],
|
| 323 |
+
quiz: {
|
| 324 |
+
passingScore: 70,
|
| 325 |
+
questions: [
|
| 326 |
+
{
|
| 327 |
+
question: 'ما هي أخطر أنواع هجمات أمان الويب؟',
|
| 328 |
+
options: ['XSS', 'SQL Injection', 'CSRF', 'جميع ما سبق'],
|
| 329 |
+
correct: 3
|
| 330 |
+
},
|
| 331 |
+
{
|
| 332 |
+
question: 'أي رأس HTTP يمنع clickjacking؟',
|
| 333 |
+
options: ['X-XSS-Protection', 'X-Frame-Options', 'Content-Security-Policy', 'X-Content-Type-Options'],
|
| 334 |
+
correct: 1
|
| 335 |
+
}
|
| 336 |
+
]
|
| 337 |
+
}
|
| 338 |
+
},
|
| 339 |
+
|
| 340 |
+
xss: {
|
| 341 |
+
id: 'xss',
|
| 342 |
+
title: 'منع هجمات XSS',
|
| 343 |
+
description: 'تعلم كيفية منع وحماية التطبيقات من هجمات Cross-Site Scripting',
|
| 344 |
+
difficulty: 'متوسط',
|
| 345 |
+
estimatedTime: '45 دقيقة',
|
| 346 |
+
lessons: [
|
| 347 |
+
{
|
| 348 |
+
id: 'xss-intro',
|
| 349 |
+
title: 'فهم هجمات XSS',
|
| 350 |
+
content: `
|
| 351 |
+
<h2>هجمات Cross-Site Scripting (XSS)</h2>
|
| 352 |
+
<p>XSS هي واحدة من أخطر التهديدات في أمان الويب، حيث تسمح للمهاجمين بحقن أكواد ضارة في صفحات الويب.</p>
|
| 353 |
+
|
| 354 |
+
<h3>أنواع XSS</h3>
|
| 355 |
+
|
| 356 |
+
<div class="xss-types">
|
| 357 |
+
<div class="xss-type">
|
| 358 |
+
<h4>Reflected XSS</h4>
|
| 359 |
+
<p>السكريبت ينعكس فوراً في الاستجابة</p>
|
| 360 |
+
<div class="code-example">
|
| 361 |
+
<pre><code>http://example.com/search?q=<script>alert('XSS')</script></code></pre>
|
| 362 |
+
</div>
|
| 363 |
+
</div>
|
| 364 |
+
|
| 365 |
+
<div class="xss-type">
|
| 366 |
+
<h4>Stored XSS</h4>
|
| 367 |
+
<p>السكريبت يُخزن في قاعدة البيانات</p>
|
| 368 |
+
<div class="example-scenario">
|
| 369 |
+
<p><strong>المثال:</strong> تعليق يحتوي على <code><script>...</script></code></p>
|
| 370 |
+
<p><strong>النتيجة:</strong> السكريبت ينفذ عند كل زائر</p>
|
| 371 |
+
</div>
|
| 372 |
+
</div>
|
| 373 |
+
|
| 374 |
+
<div class="xss-type">
|
| 375 |
+
<h4>DOM-based XSS</h4>
|
| 376 |
+
<p>السكريبت ينفذ عبر JavaScript</p>
|
| 377 |
+
<div class="code-example">
|
| 378 |
+
<pre><code>document.getElementById("output").innerHTML =
|
| 379 |
+
"Welcome " + userInput;</code></pre>
|
| 380 |
+
</div>
|
| 381 |
+
</div>
|
| 382 |
+
</div>
|
| 383 |
+
|
| 384 |
+
<div class="attack-demo">
|
| 385 |
+
<h4>تجربة تفاعلية: XSS Attack</h4>
|
| 386 |
+
<p>هذه محاكاة آمنة لهجوم XSS:</p>
|
| 387 |
+
|
| 388 |
+
<div class="demo-input">
|
| 389 |
+
<label>أدخل تعليقك:</label>
|
| 390 |
+
<textarea id="xss-input" placeholder="مثال: أحب هذا الموقع!"></textarea>
|
| 391 |
+
</div>
|
| 392 |
+
|
| 393 |
+
<div class="demo-output">
|
| 394 |
+
<h5>كيف سيظهر تعليقك:</h5>
|
| 395 |
+
<div id="xss-output" class="comment-display"></div>
|
| 396 |
+
</div>
|
| 397 |
+
|
| 398 |
+
<div class="demo-actions">
|
| 399 |
+
<button onclick="simulateXSS()">تجربة XSS</button>
|
| 400 |
+
<button onclick="resetDemo()">إعادة تعيين</button>
|
| 401 |
+
</div>
|
| 402 |
+
|
| 403 |
+
<div id="xss-warning" class="warning-box" style="display: none;">
|
| 404 |
+
<strong>تحذير!</strong> تم اكتشاف محاولة XSS. هذا مثال على خطر XSS.
|
| 405 |
+
</div>
|
| 406 |
+
</div>
|
| 407 |
+
|
| 408 |
+
<h3>تقنيات الحماية</h3>
|
| 409 |
+
<div class="protection-methods">
|
| 410 |
+
<div class="method">
|
| 411 |
+
<h4>1. ترميز المدخلات</h4>
|
| 412 |
+
<p>تحويل الأحرف الخاصة إلى HTML entities</p>
|
| 413 |
+
<div class="code-example">
|
| 414 |
+
<pre><code>function escapeHtml(text) {
|
| 415 |
+
const div = document.createElement('div');
|
| 416 |
+
div.textContent = text;
|
| 417 |
+
return div.innerHTML;
|
| 418 |
+
}</code></pre>
|
| 419 |
+
</div>
|
| 420 |
+
</div>
|
| 421 |
+
|
| 422 |
+
<div class="method">
|
| 423 |
+
<h4>2. استخدام Content Security Policy</h4>
|
| 424 |
+
<p>منع تحميل السكريبتات من مصادر غير موثوقة</p>
|
| 425 |
+
<div class="code-example">
|
| 426 |
+
<pre><code>Content-Security-Policy: script-src 'self'</code></pre>
|
| 427 |
+
</div>
|
| 428 |
+
</div>
|
| 429 |
+
|
| 430 |
+
<div class="method">
|
| 431 |
+
<h4>3. استخدام Trusted Types</h4>
|
| 432 |
+
<p>منع استخدام innerHTML بشكل مباشر</p>
|
| 433 |
+
<div class="code-example">
|
| 434 |
+
<pre><code>if (window.trustedTypes) {
|
| 435 |
+
const policy = trustedTypes.createPolicy('default', {
|
| 436 |
+
createHTML: (input) => input
|
| 437 |
+
});
|
| 438 |
+
}</code></pre>
|
| 439 |
+
</div>
|
| 440 |
+
</div>
|
| 441 |
+
</div>
|
| 442 |
+
`,
|
| 443 |
+
quiz: {
|
| 444 |
+
question: 'أي نوع من XSS يُخزن في قاعدة البيانات؟',
|
| 445 |
+
options: ['Reflected XSS', 'Stored XSS', 'DOM-based XSS', 'Blind XSS'],
|
| 446 |
+
correct: 1,
|
| 447 |
+
explanation: 'Stored XSS يتم حفظه في قاعدة البيانات ويُنفذ عند كل زائر للصفحة.'
|
| 448 |
+
}
|
| 449 |
+
},
|
| 450 |
+
{
|
| 451 |
+
id: 'xss-prevention',
|
| 452 |
+
title: 'استراتيجيات منع XSS',
|
| 453 |
+
content: `
|
| 454 |
+
<h2>استراتيجيات منع XSS</h2>
|
| 455 |
+
<p>تطبيق استراتيجيات متعددة الطبقات للحماية من هجمات XSS.</p>
|
| 456 |
+
|
| 457 |
+
<h3>1. ترميز البيانات</h3>
|
| 458 |
+
<div class="encoding-demo">
|
| 459 |
+
<p>جرب ترميز المدخلات المختلفة:</p>
|
| 460 |
+
<input type="text" id="encoding-input" placeholder="أدخل نص للترميز">
|
| 461 |
+
<button onclick="encodeInput()">ترميز</button>
|
| 462 |
+
<div id="encoding-output" class="output-box"></div>
|
| 463 |
+
</div>
|
| 464 |
+
|
| 465 |
+
<h3>2. التحقق من المدخلات</h3>
|
| 466 |
+
<div class="validation-demo">
|
| 467 |
+
<p>التحقق من صحة المدخلات:</p>
|
| 468 |
+
<input type="text" id="validation-input" placeholder="أدخل بريد إلكتروني">
|
| 469 |
+
<button onclick="validateInput()">التحقق</button>
|
| 470 |
+
<div id="validation-result" class="validation-result"></div>
|
| 471 |
+
</div>
|
| 472 |
+
|
| 473 |
+
<h3>3. استخدام libraries آمنة</h3>
|
| 474 |
+
<div class="library-comparison">
|
| 475 |
+
<div class="library-bad">
|
| 476 |
+
<h4>❌ غير آمن</h4>
|
| 477 |
+
<pre><code>element.innerHTML = userInput;</code></pre>
|
| 478 |
+
</div>
|
| 479 |
+
<div class="library-good">
|
| 480 |
+
<h4>✅ آمن</h4>
|
| 481 |
+
<pre><code>element.textContent = userInput;</code></pre>
|
| 482 |
+
</div>
|
| 483 |
+
</div>
|
| 484 |
+
|
| 485 |
+
<h3>4. تطبيق CSP مع strict-dynamic</h3>
|
| 486 |
+
<div class="csp-strict-demo">
|
| 487 |
+
<p>مثال على CSP صارمة:</p>
|
| 488 |
+
<div class="code-example">
|
| 489 |
+
<pre><code>Content-Security-Policy:
|
| 490 |
+
default-src 'none';
|
| 491 |
+
script-src 'self' 'strict-dynamic' 'nonce-abc123';
|
| 492 |
+
style-src 'self';
|
| 493 |
+
img-src 'self' data:;
|
| 494 |
+
connect-src 'self';
|
| 495 |
+
frame-ancestors 'none';</code></pre>
|
| 496 |
+
</div>
|
| 497 |
+
</div>
|
| 498 |
+
`,
|
| 499 |
+
quiz: {
|
| 500 |
+
question: 'أي من الطرق التالية هو الأكثر أماناً لعرض نص من المستخدم؟',
|
| 501 |
+
options: ['innerHTML', 'outerHTML', 'textContent', 'insertAdjacentHTML'],
|
| 502 |
+
correct: 2,
|
| 503 |
+
explanation: 'textContent يُعرض النص كنص عادي ولا ينفذ HTML أو JavaScript.'
|
| 504 |
+
}
|
| 505 |
+
}
|
| 506 |
+
]
|
| 507 |
+
},
|
| 508 |
+
|
| 509 |
+
csrf: {
|
| 510 |
+
id: 'csrf',
|
| 511 |
+
title: 'حماية من CSRF',
|
| 512 |
+
description: 'تعلم كيفية حماية تطبيقك من هجمات Cross-Site Request Forgery',
|
| 513 |
+
difficulty: 'متوسط',
|
| 514 |
+
estimatedTime: '40 دقيقة',
|
| 515 |
+
lessons: [
|
| 516 |
+
{
|
| 517 |
+
id: 'csrf-intro',
|
| 518 |
+
title: 'فهم هجمات CSRF',
|
| 519 |
+
content: `
|
| 520 |
+
<h2>Cross-Site Request Forgery (CSRF)</h2>
|
| 521 |
+
<p>CSRF يستغل ثقة الموقع في متصفح المستخدم لتنفيذ إجراءات غير ��رغوب فيها.</p>
|
| 522 |
+
|
| 523 |
+
<h3>كيف تعمل هجمات CSRF؟</h3>
|
| 524 |
+
<div class="csrf-flow">
|
| 525 |
+
<div class="flow-step">
|
| 526 |
+
<div class="step-number">1</div>
|
| 527 |
+
<div class="step-content">
|
| 528 |
+
<strong>المستخدم يدخل موقعه البنكي</strong>
|
| 529 |
+
<p>المستخدم مسجل دخول في موقع البنك</p>
|
| 530 |
+
</div>
|
| 531 |
+
</div>
|
| 532 |
+
<div class="flow-arrow">↓</div>
|
| 533 |
+
<div class="flow-step">
|
| 534 |
+
<div class="step-number">2</div>
|
| 535 |
+
<div class="step-content">
|
| 536 |
+
<strong>الانتقال لموقع ضار</strong>
|
| 537 |
+
<p>ينقر على رابط في بريد إلكتروني أو موقع</p>
|
| 538 |
+
</div>
|
| 539 |
+
</div>
|
| 540 |
+
<div class="flow-arrow">↓</div>
|
| 541 |
+
<div class="flow-step">
|
| 542 |
+
<div class="step-number">3</div>
|
| 543 |
+
<div class="step-content">
|
| 544 |
+
<strong>توليد طلب ضار</strong>
|
| 545 |
+
<p>الموقع الضار يرسل طلب لتحويل أموال</p>
|
| 546 |
+
</div>
|
| 547 |
+
</div>
|
| 548 |
+
<div class="flow-arrow">↓</div>
|
| 549 |
+
<div class="flow-step">
|
| 550 |
+
<div class="step-number">4</div>
|
| 551 |
+
<div class="step-content">
|
| 552 |
+
<strong>تنفيذ الإجراء</strong>
|
| 553 |
+
<p>البنك يثق في الطلب ويُنفذه</p>
|
| 554 |
+
</div>
|
| 555 |
+
</div>
|
| 556 |
+
</div>
|
| 557 |
+
|
| 558 |
+
<h3>مثال عملي</h3>
|
| 559 |
+
<div class="csrf-example">
|
| 560 |
+
<div class="malicious-site">
|
| 561 |
+
<h4>الموقع الضار</h4>
|
| 562 |
+
<pre><code><form action="https://bank.com/transfer" method="POST">
|
| 563 |
+
<input type="hidden" name="to" value="hacker-account">
|
| 564 |
+
<input type="hidden" name="amount" value="1000">
|
| 565 |
+
<input type="submit" value="فوز مجاني!">
|
| 566 |
+
</form></code></pre>
|
| 567 |
+
</div>
|
| 568 |
+
</div>
|
| 569 |
+
|
| 570 |
+
<div class="csrf-demo">
|
| 571 |
+
<h4>محاكاة آمنة لهجوم CSRF</h4>
|
| 572 |
+
<p>هذه محاكاة توضح كيف يمكن استغلال الثقة:</p>
|
| 573 |
+
|
| 574 |
+
<div class="demo-scenario">
|
| 575 |
+
<div class="scenario-bank">
|
| 576 |
+
<h5>موقع البنك (آمن)</h5>
|
| 577 |
+
<p>أنت مسجل دخول في البنك</p>
|
| 578 |
+
<p>رصيدك: $10,000</p>
|
| 579 |
+
</div>
|
| 580 |
+
|
| 581 |
+
<div class="scenario-attacker">
|
| 582 |
+
<h5>الموقع الضار</h5>
|
| 583 |
+
<p>محتوى: "انقر للفوز بجائزة!"</p>
|
| 584 |
+
<form action="#" onsubmit="simulateCSRF(event)">
|
| 585 |
+
<input type="hidden" name="transfer" value="1000">
|
| 586 |
+
<button type="submit">احصل على جائزتك!</button>
|
| 587 |
+
</form>
|
| 588 |
+
</div>
|
| 589 |
+
|
| 590 |
+
<div id="csrf-result" class="demo-result"></div>
|
| 591 |
+
</div>
|
| 592 |
+
</div>
|
| 593 |
+
|
| 594 |
+
<h3>طرق الحماية</h3>
|
| 595 |
+
<div class="protection-strategies">
|
| 596 |
+
<div class="strategy">
|
| 597 |
+
<h4>1. CSRF Tokens</h4>
|
| 598 |
+
<p>رموز فريدة لكل طلب</p>
|
| 599 |
+
<div class="code-example">
|
| 600 |
+
<pre><code><form method="POST">
|
| 601 |
+
<input type="hidden" name="_token" value="{{ csrf_token() }}">
|
| 602 |
+
<input type="text" name="username">
|
| 603 |
+
<button type="submit">تسجيل</button>
|
| 604 |
+
</form></code></pre>
|
| 605 |
+
</div>
|
| 606 |
+
</div>
|
| 607 |
+
|
| 608 |
+
<div class="strategy">
|
| 609 |
+
<h4>2. SameSite Cookies</h4>
|
| 610 |
+
<p>منع إرسال الكوكيز عبر الطلبات الخارجية</p>
|
| 611 |
+
<div class="code-example">
|
| 612 |
+
<pre><code>Set-Cookie: sessionid=abc123;
|
| 613 |
+
SameSite=Strict; Secure; HttpOnly</code></pre>
|
| 614 |
+
</div>
|
| 615 |
+
</div>
|
| 616 |
+
|
| 617 |
+
<div class="strategy">
|
| 618 |
+
<h4>3. Double Submit Cookie</h4>
|
| 619 |
+
<p>إرسال الرمز في كل من الكوكيز والرأس</p>
|
| 620 |
+
<div class="code-example">
|
| 621 |
+
<pre><code>// في الكوكيز
|
| 622 |
+
csrf_token=xyz789
|
| 623 |
+
|
| 624 |
+
// في الرأس
|
| 625 |
+
X-CSRF-TOKEN: xyz789</code></pre>
|
| 626 |
+
</div>
|
| 627 |
+
</div>
|
| 628 |
+
</div>
|
| 629 |
+
`,
|
| 630 |
+
quiz: {
|
| 631 |
+
question: 'ما هو الغرض من SameSite cookies؟',
|
| 632 |
+
options: [
|
| 633 |
+
'تسريع الموقع',
|
| 634 |
+
'منع إرسال الكوكيز عبر الطلبات الخارجية',
|
| 635 |
+
'تشفير البيانات',
|
| 636 |
+
'حفظ الجلسات'
|
| 637 |
+
],
|
| 638 |
+
correct: 1,
|
| 639 |
+
explanation: 'SameSite cookies تمنع إرسال الكوكيز في الطلبات من مواقع خارجية، مما يمنع هجمات CSRF.'
|
| 640 |
+
}
|
| 641 |
+
}
|
| 642 |
+
]
|
| 643 |
+
}
|
| 644 |
+
};
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
/**
|
| 648 |
+
* تهيئة السيناريوهات التفاعلية
|
| 649 |
+
* Initialize interactive scenarios
|
| 650 |
+
*/
|
| 651 |
+
initializeScenarios() {
|
| 652 |
+
return {
|
| 653 |
+
vulnerabilityScanning: {
|
| 654 |
+
id: 'vuln-scan',
|
| 655 |
+
title: 'مسح الثغرات الأمنية',
|
| 656 |
+
description: 'تعلم كيفية مسح التطبيقات للعثور على الثغرات الأمنية',
|
| 657 |
+
scenario: {
|
| 658 |
+
environment: 'تطبيق ويب تجريبي',
|
| 659 |
+
vulnerabilities: [
|
| 660 |
+
{ type: 'XSS', severity: 'high', location: 'صفحة البحث', description: 'عدم ترميز المدخلات' },
|
| 661 |
+
{ type: 'CSRF', severity: 'medium', location: 'نموذج تغيير كلمة المرور', description: 'عدم وجود CSRF token' },
|
| 662 |
+
{ type: 'SQL Injection', severity: 'critical', location: 'صفحة تسجيل الدخول', description: 'استعلامات غير محمية' }
|
| 663 |
+
],
|
| 664 |
+
tools: ['مولد CSP', 'محلل الثغرات', 'فاحص الأمان']
|
| 665 |
+
}
|
| 666 |
+
},
|
| 667 |
+
|
| 668 |
+
incidentResponse: {
|
| 669 |
+
id: 'incident-response',
|
| 670 |
+
title: 'الاستجابة للحوادث الأمنية',
|
| 671 |
+
description: 'تدرب على الاستجابة للحوادث الأمنية',
|
| 672 |
+
scenario: {
|
| 673 |
+
incident: 'هجوم XSS على الموقع',
|
| 674 |
+
timeline: [
|
| 675 |
+
{ time: '09:00', event: 'اكتشاف نشاط مشبوه', action: 'investigate' },
|
| 676 |
+
{ time: '09:15', event: 'تأكيد الهجوم', action: 'respond' },
|
| 677 |
+
{ time: '09:30', event: 'تطبيق إجراءات الطوارئ', action: 'mitigate' },
|
| 678 |
+
{ time: '10:00', event: 'إصلاح الثغرة', action: 'fix' }
|
| 679 |
+
],
|
| 680 |
+
options: [
|
| 681 |
+
{ text: 'إيقاف الموقع فوراً', consequences: 'منع المزيد من الضرر ولكن يفوت الأرباح' },
|
| 682 |
+
{ text: 'مراقبة الوضع أولاً', consequences: 'قد يزيد الضرر' },
|
| 683 |
+
{ text: 'تطبيق تصحيح سريع', consequences: 'قد لا يكون فعالاً' }
|
| 684 |
+
]
|
| 685 |
+
}
|
| 686 |
+
}
|
| 687 |
+
};
|
| 688 |
+
}
|
| 689 |
+
|
| 690 |
+
/**
|
| 691 |
+
* بدء وحدة التدريب
|
| 692 |
+
* Start training module
|
| 693 |
+
*/
|
| 694 |
+
startModule(moduleId) {
|
| 695 |
+
const module = this.modules[moduleId];
|
| 696 |
+
if (!module) {
|
| 697 |
+
throw new Error(`الوحدة ${moduleId} غير موجودة`);
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
this.currentModule = module;
|
| 701 |
+
this.currentLesson = 0;
|
| 702 |
+
this.updateProgress();
|
| 703 |
+
|
| 704 |
+
return this.renderCurrentLesson();
|
| 705 |
+
}
|
| 706 |
+
|
| 707 |
+
/**
|
| 708 |
+
* عرض الدرس الحالي
|
| 709 |
+
* Render current lesson
|
| 710 |
+
*/
|
| 711 |
+
renderCurrentLesson() {
|
| 712 |
+
if (!this.currentModule || !this.currentModule.lessons[this.currentLesson]) {
|
| 713 |
+
return null;
|
| 714 |
+
}
|
| 715 |
+
|
| 716 |
+
const lesson = this.currentModule.lessons[this.currentLesson];
|
| 717 |
+
return {
|
| 718 |
+
module: this.currentModule,
|
| 719 |
+
lesson: lesson,
|
| 720 |
+
progress: {
|
| 721 |
+
current: this.currentLesson + 1,
|
| 722 |
+
total: this.currentModule.lessons.length,
|
| 723 |
+
percentage: Math.round(((this.currentLesson + 1) / this.currentModule.lessons.length) * 100)
|
| 724 |
+
}
|
| 725 |
+
};
|
| 726 |
+
}
|
| 727 |
+
|
| 728 |
+
/**
|
| 729 |
+
* الانتقال للدرس التالي
|
| 730 |
+
* Move to next lesson
|
| 731 |
+
*/
|
| 732 |
+
nextLesson() {
|
| 733 |
+
if (!this.currentModule) return false;
|
| 734 |
+
|
| 735 |
+
if (this.currentLesson < this.currentModule.lessons.length - 1) {
|
| 736 |
+
this.currentLesson++;
|
| 737 |
+
this.updateProgress();
|
| 738 |
+
return true;
|
| 739 |
+
}
|
| 740 |
+
return false;
|
| 741 |
+
}
|
| 742 |
+
|
| 743 |
+
/**
|
| 744 |
+
* الانتقال للدرس السابق
|
| 745 |
+
* Move to previous lesson
|
| 746 |
+
*/
|
| 747 |
+
previousLesson() {
|
| 748 |
+
if (!this.currentModule) return false;
|
| 749 |
+
|
| 750 |
+
if (this.currentLesson > 0) {
|
| 751 |
+
this.currentLesson--;
|
| 752 |
+
this.updateProgress();
|
| 753 |
+
return true;
|
| 754 |
+
}
|
| 755 |
+
return false;
|
| 756 |
+
}
|
| 757 |
+
|
| 758 |
+
/**
|
| 759 |
+
* إكمال الدرس
|
| 760 |
+
* Complete lesson
|
| 761 |
+
*/
|
| 762 |
+
completeLesson() {
|
| 763 |
+
if (!this.currentModule) return;
|
| 764 |
+
|
| 765 |
+
const lessonId = this.currentModule.lessons[this.currentLesson].id;
|
| 766 |
+
if (!this.progress.completedLessons.includes(lessonId)) {
|
| 767 |
+
this.progress.completedLessons.push(lessonId);
|
| 768 |
+
this.updateProgress();
|
| 769 |
+
}
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
/**
|
| 773 |
+
* أداء الاختبار
|
| 774 |
+
* Take quiz
|
| 775 |
+
*/
|
| 776 |
+
takeQuiz(moduleId, answers) {
|
| 777 |
+
const module = this.modules[moduleId];
|
| 778 |
+
if (!module || !module.quiz) {
|
| 779 |
+
throw new Error('الوحدة أو الاختبار غير موجود');
|
| 780 |
+
}
|
| 781 |
+
|
| 782 |
+
const quiz = module.quiz;
|
| 783 |
+
let score = 0;
|
| 784 |
+
|
| 785 |
+
quiz.questions.forEach((question, index) => {
|
| 786 |
+
if (answers[index] === question.correct) {
|
| 787 |
+
score++;
|
| 788 |
+
}
|
| 789 |
+
});
|
| 790 |
+
|
| 791 |
+
const percentage = Math.round((score / quiz.questions.length) * 100);
|
| 792 |
+
const passed = percentage >= quiz.passingScore;
|
| 793 |
+
|
| 794 |
+
const result = {
|
| 795 |
+
moduleId,
|
| 796 |
+
score,
|
| 797 |
+
total: quiz.questions.length,
|
| 798 |
+
percentage,
|
| 799 |
+
passed,
|
| 800 |
+
timestamp: new Date().toISOString()
|
| 801 |
+
};
|
| 802 |
+
|
| 803 |
+
// حفظ النتيجة
|
| 804 |
+
this.quizResults.push(result);
|
| 805 |
+
this.saveQuizResults();
|
| 806 |
+
|
| 807 |
+
// منح الإنجاز
|
| 808 |
+
if (passed) {
|
| 809 |
+
this.unlockAchievement(`quiz_${moduleId}`);
|
| 810 |
+
}
|
| 811 |
+
|
| 812 |
+
return result;
|
| 813 |
+
}
|
| 814 |
+
|
| 815 |
+
/**
|
| 816 |
+
* تشغيل سيناريو تفاعلي
|
| 817 |
+
* Run interactive scenario
|
| 818 |
+
*/
|
| 819 |
+
runScenario(scenarioId, userChoices = []) {
|
| 820 |
+
const scenario = this.scenarios[scenarioId];
|
| 821 |
+
if (!scenario) {
|
| 822 |
+
throw new Error(`السيناريو ${scenarioId} غير موجود`);
|
| 823 |
+
}
|
| 824 |
+
|
| 825 |
+
const scenarioResult = {
|
| 826 |
+
scenarioId,
|
| 827 |
+
choices: userChoices,
|
| 828 |
+
score: this.calculateScenarioScore(scenario, userChoices),
|
| 829 |
+
completed: true,
|
| 830 |
+
timestamp: new Date().toISOString()
|
| 831 |
+
};
|
| 832 |
+
|
| 833 |
+
// حفظ النتيجة
|
| 834 |
+
if (!this.progress.scenarios) {
|
| 835 |
+
this.progress.scenarios = [];
|
| 836 |
+
}
|
| 837 |
+
this.progress.scenarios.push(scenarioResult);
|
| 838 |
+
this.updateProgress();
|
| 839 |
+
|
| 840 |
+
return scenarioResult;
|
| 841 |
+
}
|
| 842 |
+
|
| 843 |
+
/**
|
| 844 |
+
* حساب نتيجة السيناريو
|
| 845 |
+
* Calculate scenario score
|
| 846 |
+
*/
|
| 847 |
+
calculateScenarioScore(scenario, choices) {
|
| 848 |
+
// منطق مبسط لحساب النتيجة
|
| 849 |
+
let score = 0;
|
| 850 |
+
|
| 851 |
+
choices.forEach((choice, index) => {
|
| 852 |
+
if (choice.correct) {
|
| 853 |
+
score += 10;
|
| 854 |
+
}
|
| 855 |
+
});
|
| 856 |
+
|
| 857 |
+
return Math.min(score, 100);
|
| 858 |
+
}
|
| 859 |
+
|
| 860 |
+
/**
|
| 861 |
+
* فتح إنجاز
|
| 862 |
+
* Unlock achievement
|
| 863 |
+
*/
|
| 864 |
+
unlockAchievement(achievementId) {
|
| 865 |
+
if (!this.achievements.find(a => a.id === achievementId)) {
|
| 866 |
+
const achievement = {
|
| 867 |
+
id: achievementId,
|
| 868 |
+
unlockedAt: new Date().toISOString(),
|
| 869 |
+
name: this.getAchievementName(achievementId),
|
| 870 |
+
description: this.getAchievementDescription(achievementId)
|
| 871 |
+
};
|
| 872 |
+
|
| 873 |
+
this.achievements.push(achievement);
|
| 874 |
+
this.saveAchievements();
|
| 875 |
+
|
| 876 |
+
return achievement;
|
| 877 |
+
}
|
| 878 |
+
return null;
|
| 879 |
+
}
|
| 880 |
+
|
| 881 |
+
/**
|
| 882 |
+
* الحصول على اسم الإنجاز
|
| 883 |
+
* Get achievement name
|
| 884 |
+
*/
|
| 885 |
+
getAchievementName(achievementId) {
|
| 886 |
+
const names = {
|
| 887 |
+
'first_lesson': 'البداية',
|
| 888 |
+
'first_module': 'المتعلم النشط',
|
| 889 |
+
'quiz_fundamentals': 'خبير الأساسيات',
|
| 890 |
+
'quiz_xss': 'محارب XSS',
|
| 891 |
+
'csrf_master': 'سيد الحماية من CSRF',
|
| 892 |
+
'perfect_score': 'الكمال المطلق'
|
| 893 |
+
};
|
| 894 |
+
return names[achievementId] || 'إنجاز جديد';
|
| 895 |
+
}
|
| 896 |
+
|
| 897 |
+
/**
|
| 898 |
+
* الحصول على وصف الإنجاز
|
| 899 |
+
* Get achievement description
|
| 900 |
+
*/
|
| 901 |
+
getAchievementDescription(achievementId) {
|
| 902 |
+
const descriptions = {
|
| 903 |
+
'first_lesson': 'أكملت أول درس',
|
| 904 |
+
'first_module': 'أكملت أول وحدة تدريب',
|
| 905 |
+
'quiz_fundamentals': 'نجحت في اختبار أساسيات أمان الويب',
|
| 906 |
+
'quiz_xss': 'أتقنت منع هجمات XSS',
|
| 907 |
+
'csrf_master': 'أصبحت خبير في حماية CSRF',
|
| 908 |
+
'perfect_score': 'حصلت على نتيجة مثالية في اختبار'
|
| 909 |
+
};
|
| 910 |
+
return descriptions[achievementId] || ' إنجاز جديد';
|
| 911 |
+
}
|
| 912 |
+
|
| 913 |
+
/**
|
| 914 |
+
* الحصول على التقدم
|
| 915 |
+
* Get progress
|
| 916 |
+
*/
|
| 917 |
+
getProgress() {
|
| 918 |
+
const totalLessons = Object.values(this.modules)
|
| 919 |
+
.reduce((total, module) => total + module.lessons.length, 0);
|
| 920 |
+
|
| 921 |
+
const completedLessons = this.progress.completedLessons.length;
|
| 922 |
+
const completedModules = Object.keys(this.modules)
|
| 923 |
+
.filter(moduleId => this.isModuleCompleted(moduleId)).length;
|
| 924 |
+
|
| 925 |
+
return {
|
| 926 |
+
...this.progress,
|
| 927 |
+
totalLessons,
|
| 928 |
+
completedLessons,
|
| 929 |
+
completedModules,
|
| 930 |
+
totalModules: Object.keys(this.modules).length,
|
| 931 |
+
lessonProgress: Math.round((completedLessons / totalLessons) * 100),
|
| 932 |
+
moduleProgress: Math.round((completedModules / Object.keys(this.modules).length) * 100)
|
| 933 |
+
};
|
| 934 |
+
}
|
| 935 |
+
|
| 936 |
+
/**
|
| 937 |
+
* فحص إكمال الوحدة
|
| 938 |
+
* Check if module is completed
|
| 939 |
+
*/
|
| 940 |
+
isModuleCompleted(moduleId) {
|
| 941 |
+
const module = this.modules[moduleId];
|
| 942 |
+
if (!module) return false;
|
| 943 |
+
|
| 944 |
+
return module.lessons.every(lesson =>
|
| 945 |
+
this.progress.completedLessons.includes(lesson.id)
|
| 946 |
+
);
|
| 947 |
+
}
|
| 948 |
+
|
| 949 |
+
/**
|
| 950 |
+
* تحديث التقدم
|
| 951 |
+
* Update progress
|
| 952 |
+
*/
|
| 953 |
+
updateProgress() {
|
| 954 |
+
this.progress.lastUpdated = new Date().toISOString();
|
| 955 |
+
this.saveProgress();
|
| 956 |
+
}
|
| 957 |
+
|
| 958 |
+
/**
|
| 959 |
+
* حفظ التقدم
|
| 960 |
+
* Save progress
|
| 961 |
+
*/
|
| 962 |
+
saveProgress() {
|
| 963 |
+
localStorage.setItem('securityTrainingProgress', JSON.stringify(this.progress));
|
| 964 |
+
}
|
| 965 |
+
|
| 966 |
+
/**
|
| 967 |
+
* تحميل التقدم
|
| 968 |
+
* Load progress
|
| 969 |
+
*/
|
| 970 |
+
loadProgress() {
|
| 971 |
+
try {
|
| 972 |
+
const saved = localStorage.getItem('securityTrainingProgress');
|
| 973 |
+
return saved ? JSON.parse(saved) : {
|
| 974 |
+
completedLessons: [],
|
| 975 |
+
modules: {},
|
| 976 |
+
scenarios: [],
|
| 977 |
+
achievements: [],
|
| 978 |
+
lastUpdated: new Date().toISOString()
|
| 979 |
+
};
|
| 980 |
+
} catch {
|
| 981 |
+
return {
|
| 982 |
+
completedLessons: [],
|
| 983 |
+
modules: {},
|
| 984 |
+
scenarios: [],
|
| 985 |
+
achievements: [],
|
| 986 |
+
lastUpdated: new Date().toISOString()
|
| 987 |
+
};
|
| 988 |
+
}
|
| 989 |
+
}
|
| 990 |
+
|
| 991 |
+
/**
|
| 992 |
+
* حفظ الإنجازات
|
| 993 |
+
* Save achievements
|
| 994 |
+
*/
|
| 995 |
+
saveAchievements() {
|
| 996 |
+
localStorage.setItem('securityTrainingAchievements', JSON.stringify(this.achievements));
|
| 997 |
+
}
|
| 998 |
+
|
| 999 |
+
/**
|
| 1000 |
+
* تحميل الإنجازات
|
| 1001 |
+
* Load achievements
|
| 1002 |
+
*/
|
| 1003 |
+
loadAchievements() {
|
| 1004 |
+
try {
|
| 1005 |
+
const saved = localStorage.getItem('securityTrainingAchievements');
|
| 1006 |
+
return saved ? JSON.parse(saved) : [];
|
| 1007 |
+
} catch {
|
| 1008 |
+
return [];
|
| 1009 |
+
}
|
| 1010 |
+
}
|
| 1011 |
+
|
| 1012 |
+
/**
|
| 1013 |
+
* حفظ نتائج الاختبارات
|
| 1014 |
+
* Save quiz results
|
| 1015 |
+
*/
|
| 1016 |
+
saveQuizResults() {
|
| 1017 |
+
localStorage.setItem('securityTrainingQuizResults', JSON.stringify(this.quizResults));
|
| 1018 |
+
}
|
| 1019 |
+
|
| 1020 |
+
/**
|
| 1021 |
+
* تحميل نتائج الاختبارات
|
| 1022 |
+
* Load quiz results
|
| 1023 |
+
*/
|
| 1024 |
+
loadQuizResults() {
|
| 1025 |
+
try {
|
| 1026 |
+
const saved = localStorage.getItem('securityTrainingQuizResults');
|
| 1027 |
+
return saved ? JSON.parse(saved) : [];
|
| 1028 |
+
} catch {
|
| 1029 |
+
return [];
|
| 1030 |
+
}
|
| 1031 |
+
}
|
| 1032 |
+
|
| 1033 |
+
/**
|
| 1034 |
+
* الحصول على الإحصائيات
|
| 1035 |
+
* Get statistics
|
| 1036 |
+
*/
|
| 1037 |
+
getStatistics() {
|
| 1038 |
+
const progress = this.getProgress();
|
| 1039 |
+
const avgQuizScore = this.quizResults.length > 0
|
| 1040 |
+
? Math.round(this.quizResults.reduce((sum, result) => sum + result.percentage, 0) / this.quizResults.length)
|
| 1041 |
+
: 0;
|
| 1042 |
+
|
| 1043 |
+
return {
|
| 1044 |
+
totalLessons: progress.totalLessons,
|
| 1045 |
+
completedLessons: progress.completedLessons,
|
| 1046 |
+
totalModules: progress.totalModules,
|
| 1047 |
+
completedModules: progress.completedModules,
|
| 1048 |
+
totalAchievements: this.achievements.length,
|
| 1049 |
+
totalQuizAttempts: this.quizResults.length,
|
| 1050 |
+
averageQuizScore: avgQuizScore,
|
| 1051 |
+
lastActivity: progress.lastUpdated
|
| 1052 |
+
};
|
| 1053 |
+
}
|
| 1054 |
+
|
| 1055 |
+
/**
|
| 1056 |
+
* تصدير التقدم
|
| 1057 |
+
* Export progress
|
| 1058 |
+
*/
|
| 1059 |
+
exportProgress() {
|
| 1060 |
+
const data = {
|
| 1061 |
+
progress: this.progress,
|
| 1062 |
+
achievements: this.achievements,
|
| 1063 |
+
quizResults: this.quizResults,
|
| 1064 |
+
statistics: this.getStatistics(),
|
| 1065 |
+
exportDate: new Date().toISOString()
|
| 1066 |
+
};
|
| 1067 |
+
|
| 1068 |
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
| 1069 |
+
const filename = `security-training-${timestamp}.json`;
|
| 1070 |
+
|
| 1071 |
+
const dataStr = JSON.stringify(data, null, 2);
|
| 1072 |
+
const dataBlob = new Blob([dataStr], { type: 'application/json' });
|
| 1073 |
+
const url = URL.createObjectURL(dataBlob);
|
| 1074 |
+
|
| 1075 |
+
const link = document.createElement('a');
|
| 1076 |
+
link.href = url;
|
| 1077 |
+
link.download = filename;
|
| 1078 |
+
link.click();
|
| 1079 |
+
|
| 1080 |
+
URL.revokeObjectURL(url);
|
| 1081 |
+
}
|
| 1082 |
+
|
| 1083 |
+
/**
|
| 1084 |
+
* إعادة تعيين التقدم
|
| 1085 |
+
* Reset progress
|
| 1086 |
+
*/
|
| 1087 |
+
resetProgress() {
|
| 1088 |
+
if (confirm('هل أنت متأكد من رغبتك في إعادة تعيين جميع التقدم؟ هذا الإجراء لا يمكن التراجع عنه.')) {
|
| 1089 |
+
this.progress = {
|
| 1090 |
+
completedLessons: [],
|
| 1091 |
+
modules: {},
|
| 1092 |
+
scenarios: [],
|
| 1093 |
+
achievements: [],
|
| 1094 |
+
lastUpdated: new Date().toISOString()
|
| 1095 |
+
};
|
| 1096 |
+
this.achievements = [];
|
| 1097 |
+
this.quizResults = [];
|
| 1098 |
+
|
| 1099 |
+
this.saveProgress();
|
| 1100 |
+
this.saveAchievements();
|
| 1101 |
+
this.saveQuizResults();
|
| 1102 |
+
|
| 1103 |
+
return true;
|
| 1104 |
+
}
|
| 1105 |
+
return false;
|
| 1106 |
+
}
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
// تصدير الكلاس للاستخدام
|
| 1110 |
+
window.SecurityTraining = SecurityTraining;
|
js/service-worker-manager.js
ADDED
|
@@ -0,0 +1,820 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* Service Worker Manager
|
| 3 |
+
* Advanced offline functionality and data persistence for security platform
|
| 4 |
+
* Author: MiniMax Agent
|
| 5 |
+
* Date: 2025-12-10
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
class ServiceWorkerManager {
|
| 9 |
+
constructor() {
|
| 10 |
+
this.registration = null;
|
| 11 |
+
this.isSupported = 'serviceWorker' in navigator;
|
| 12 |
+
this.cacheNames = {
|
| 13 |
+
static: 'security-platform-static-v1',
|
| 14 |
+
dynamic: 'security-platform-dynamic-v1',
|
| 15 |
+
api: 'security-platform-api-v1',
|
| 16 |
+
analysis: 'security-platform-analysis-v1',
|
| 17 |
+
training: 'security-platform-training-v1'
|
| 18 |
+
};
|
| 19 |
+
this.syncQueue = [];
|
| 20 |
+
this.offlineData = new Map();
|
| 21 |
+
this.backgroundSync = false;
|
| 22 |
+
this.pushNotifications = false;
|
| 23 |
+
this.installPrompt = null;
|
| 24 |
+
}
|
| 25 |
+
|
| 26 |
+
async initialize() {
|
| 27 |
+
try {
|
| 28 |
+
if (!this.isSupported) {
|
| 29 |
+
throw new Error('Service Workers not supported');
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
console.log('🌐 Initializing Service Worker Manager...');
|
| 33 |
+
|
| 34 |
+
// Register service worker
|
| 35 |
+
await this.registerServiceWorker();
|
| 36 |
+
|
| 37 |
+
// Setup offline functionality
|
| 38 |
+
await this.setupOfflineCapabilities();
|
| 39 |
+
|
| 40 |
+
// Initialize background sync
|
| 41 |
+
await this.setupBackgroundSync();
|
| 42 |
+
|
| 43 |
+
// Setup push notifications
|
| 44 |
+
await this.setupPushNotifications();
|
| 45 |
+
|
| 46 |
+
// Setup data persistence
|
| 47 |
+
await this.setupDataPersistence();
|
| 48 |
+
|
| 49 |
+
// Setup install prompt
|
| 50 |
+
this.setupInstallPrompt();
|
| 51 |
+
|
| 52 |
+
console.log('✅ Service Worker Manager initialized successfully');
|
| 53 |
+
|
| 54 |
+
} catch (error) {
|
| 55 |
+
console.error('❌ Failed to initialize Service Worker:', error);
|
| 56 |
+
this.fallbackToLocalStorage();
|
| 57 |
+
}
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
async registerServiceWorker() {
|
| 61 |
+
try {
|
| 62 |
+
// Create service worker content
|
| 63 |
+
const swContent = this.generateServiceWorkerContent();
|
| 64 |
+
const swBlob = new Blob([swContent], { type: 'application/javascript' });
|
| 65 |
+
const swUrl = URL.createObjectURL(swBlob);
|
| 66 |
+
|
| 67 |
+
this.registration = await navigator.serviceWorker.register(swUrl, {
|
| 68 |
+
scope: './'
|
| 69 |
+
});
|
| 70 |
+
|
| 71 |
+
console.log('✅ Service Worker registered:', this.registration.scope);
|
| 72 |
+
|
| 73 |
+
// Handle service worker updates
|
| 74 |
+
this.registration.addEventListener('updatefound', () => {
|
| 75 |
+
const newWorker = this.registration.installing;
|
| 76 |
+
newWorker.addEventListener('statechange', () => {
|
| 77 |
+
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
|
| 78 |
+
this.showUpdateAvailable();
|
| 79 |
+
}
|
| 80 |
+
});
|
| 81 |
+
});
|
| 82 |
+
|
| 83 |
+
} catch (error) {
|
| 84 |
+
console.error('Service Worker registration failed:', error);
|
| 85 |
+
throw error;
|
| 86 |
+
}
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
generateServiceWorkerContent() {
|
| 90 |
+
return `
|
| 91 |
+
const CACHE_NAMES = {
|
| 92 |
+
static: 'security-platform-static-v1',
|
| 93 |
+
dynamic: 'security-platform-dynamic-v1',
|
| 94 |
+
api: 'security-platform-api-v1',
|
| 95 |
+
analysis: 'security-platform-analysis-v1',
|
| 96 |
+
training: 'security-platform-training-v1'
|
| 97 |
+
};
|
| 98 |
+
|
| 99 |
+
const STATIC_ASSETS = [
|
| 100 |
+
'./',
|
| 101 |
+
'./index.html',
|
| 102 |
+
'./advanced-security-platform.html',
|
| 103 |
+
'./styles/main.css',
|
| 104 |
+
'./styles/dark-theme.css',
|
| 105 |
+
'./js/ai-threat-analyzer.js',
|
| 106 |
+
'./js/real-time-monitor.js',
|
| 107 |
+
'./js/smart-policy-generator.js',
|
| 108 |
+
'./js/security-training.js',
|
| 109 |
+
'./js/security-dashboard.js',
|
| 110 |
+
'./js/wasm-security-analyzer.js',
|
| 111 |
+
'./js/ai-behavioral-analyzer.js',
|
| 112 |
+
'./js/3d-interactive-interface.js'
|
| 113 |
+
];
|
| 114 |
+
|
| 115 |
+
// Install event - cache static assets
|
| 116 |
+
self.addEventListener('install', event => {
|
| 117 |
+
console.log('🔧 Service Worker installing...');
|
| 118 |
+
event.waitUntil(
|
| 119 |
+
caches.open(CACHE_NAMES.static)
|
| 120 |
+
.then(cache => {
|
| 121 |
+
console.log('📦 Caching static assets');
|
| 122 |
+
return cache.addAll(STATIC_ASSETS);
|
| 123 |
+
})
|
| 124 |
+
.then(() => self.skipWaiting())
|
| 125 |
+
);
|
| 126 |
+
});
|
| 127 |
+
|
| 128 |
+
// Activate event - cleanup old caches
|
| 129 |
+
self.addEventListener('activate', event => {
|
| 130 |
+
console.log('🚀 Service Worker activating...');
|
| 131 |
+
event.waitUntil(
|
| 132 |
+
caches.keys()
|
| 133 |
+
.then(cacheNames => {
|
| 134 |
+
return Promise.all(
|
| 135 |
+
cacheNames.map(cacheName => {
|
| 136 |
+
if (!Object.values(CACHE_NAMES).includes(cacheName)) {
|
| 137 |
+
console.log('🗑️ Deleting old cache:', cacheName);
|
| 138 |
+
return caches.delete(cacheName);
|
| 139 |
+
}
|
| 140 |
+
})
|
| 141 |
+
);
|
| 142 |
+
})
|
| 143 |
+
.then(() => self.clients.claim())
|
| 144 |
+
);
|
| 145 |
+
});
|
| 146 |
+
|
| 147 |
+
// Fetch event - serve from cache with network fallback
|
| 148 |
+
self.addEventListener('fetch', event => {
|
| 149 |
+
const { request } = event;
|
| 150 |
+
const url = new URL(request.url);
|
| 151 |
+
|
| 152 |
+
// Handle different types of requests
|
| 153 |
+
if (request.method === 'GET') {
|
| 154 |
+
if (url.pathname.endsWith('.js') || url.pathname.endsWith('.css')) {
|
| 155 |
+
// Cache static assets with stale-while-revalidate
|
| 156 |
+
event.respondWith(staleWhileRevalidate(request, CACHE_NAMES.static));
|
| 157 |
+
} else if (url.pathname.includes('/api/')) {
|
| 158 |
+
// Cache API responses with network-first
|
| 159 |
+
event.respondWith(networkFirst(request, CACHE_NAMES.api));
|
| 160 |
+
} else if (url.pathname.includes('/analysis/')) {
|
| 161 |
+
// Cache analysis data with cache-first
|
| 162 |
+
event.respondWith(cacheFirst(request, CACHE_NAMES.analysis));
|
| 163 |
+
} else {
|
| 164 |
+
// Default: network-first with cache fallback
|
| 165 |
+
event.respondWith(networkFirst(request, CACHE_NAMES.dynamic));
|
| 166 |
+
}
|
| 167 |
+
} else if (request.method === 'POST') {
|
| 168 |
+
// Queue POST requests for background sync
|
| 169 |
+
event.respondWith(handlePostRequest(request));
|
| 170 |
+
}
|
| 171 |
+
});
|
| 172 |
+
|
| 173 |
+
// Background sync event
|
| 174 |
+
self.addEventListener('sync', event => {
|
| 175 |
+
console.log('🔄 Background sync triggered:', event.tag);
|
| 176 |
+
if (event.tag === 'security-analysis-sync') {
|
| 177 |
+
event.waitUntil(syncSecurityData());
|
| 178 |
+
}
|
| 179 |
+
});
|
| 180 |
+
|
| 181 |
+
// Push notification event
|
| 182 |
+
self.addEventListener('push', event => {
|
| 183 |
+
console.log('📱 Push notification received');
|
| 184 |
+
const options = {
|
| 185 |
+
body: event.data ? event.data.text() : 'New security alert',
|
| 186 |
+
icon: '/icon-192x192.png',
|
| 187 |
+
badge: '/badge-72x72.png',
|
| 188 |
+
tag: 'security-alert',
|
| 189 |
+
requireInteraction: true,
|
| 190 |
+
actions: [
|
| 191 |
+
{
|
| 192 |
+
action: 'view',
|
| 193 |
+
title: 'View Details'
|
| 194 |
+
},
|
| 195 |
+
{
|
| 196 |
+
action: 'dismiss',
|
| 197 |
+
title: 'Dismiss'
|
| 198 |
+
}
|
| 199 |
+
]
|
| 200 |
+
};
|
| 201 |
+
|
| 202 |
+
event.waitUntil(
|
| 203 |
+
self.registration.showNotification('Security Alert', options)
|
| 204 |
+
);
|
| 205 |
+
});
|
| 206 |
+
|
| 207 |
+
// Notification click event
|
| 208 |
+
self.addEventListener('notificationclick', event => {
|
| 209 |
+
console.log('👆 Notification clicked:', event.action);
|
| 210 |
+
event.notification.close();
|
| 211 |
+
|
| 212 |
+
if (event.action === 'view') {
|
| 213 |
+
event.waitUntil(
|
| 214 |
+
clients.openWindow('/security-dashboard')
|
| 215 |
+
);
|
| 216 |
+
}
|
| 217 |
+
});
|
| 218 |
+
|
| 219 |
+
// Cache strategies
|
| 220 |
+
async function staleWhileRevalidate(request, cacheName) {
|
| 221 |
+
const cache = await caches.open(cacheName);
|
| 222 |
+
const cachedResponse = await cache.match(request);
|
| 223 |
+
|
| 224 |
+
const networkPromise = fetch(request).then(response => {
|
| 225 |
+
cache.put(request, response.clone());
|
| 226 |
+
return response;
|
| 227 |
+
}).catch(() => cachedResponse);
|
| 228 |
+
|
| 229 |
+
return cachedResponse || networkPromise;
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
async function networkFirst(request, cacheName) {
|
| 233 |
+
const cache = await caches.open(cacheName);
|
| 234 |
+
try {
|
| 235 |
+
const response = await fetch(request);
|
| 236 |
+
cache.put(request, response.clone());
|
| 237 |
+
return response;
|
| 238 |
+
} catch (error) {
|
| 239 |
+
const cachedResponse = await cache.match(request);
|
| 240 |
+
if (cachedResponse) {
|
| 241 |
+
return cachedResponse;
|
| 242 |
+
}
|
| 243 |
+
throw error;
|
| 244 |
+
}
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
async function cacheFirst(request, cacheName) {
|
| 248 |
+
const cache = await caches.open(cacheName);
|
| 249 |
+
const cachedResponse = await cache.match(request);
|
| 250 |
+
if (cachedResponse) {
|
| 251 |
+
return cachedResponse;
|
| 252 |
+
}
|
| 253 |
+
const response = await fetch(request);
|
| 254 |
+
cache.put(request, response.clone());
|
| 255 |
+
return response;
|
| 256 |
+
}
|
| 257 |
+
|
| 258 |
+
async function handlePostRequest(request) {
|
| 259 |
+
try {
|
| 260 |
+
const response = await fetch(request.clone());
|
| 261 |
+
return response;
|
| 262 |
+
} catch (error) {
|
| 263 |
+
// Store failed request for retry
|
| 264 |
+
const requestData = {
|
| 265 |
+
url: request.url,
|
| 266 |
+
method: request.method,
|
| 267 |
+
headers: Object.fromEntries(request.headers.entries()),
|
| 268 |
+
body: await request.text(),
|
| 269 |
+
timestamp: Date.now()
|
| 270 |
+
};
|
| 271 |
+
|
| 272 |
+
await storeFailedRequest(requestData);
|
| 273 |
+
|
| 274 |
+
// Return success response to prevent app from breaking
|
| 275 |
+
return new Response(JSON.stringify({
|
| 276 |
+
status: 'queued',
|
| 277 |
+
message: 'Request queued for background sync'
|
| 278 |
+
}), {
|
| 279 |
+
status: 202,
|
| 280 |
+
headers: { 'Content-Type': 'application/json' }
|
| 281 |
+
});
|
| 282 |
+
}
|
| 283 |
+
}
|
| 284 |
+
|
| 285 |
+
async function storeFailedRequest(requestData) {
|
| 286 |
+
const db = await openDB();
|
| 287 |
+
const transaction = db.transaction(['requests'], 'readwrite');
|
| 288 |
+
const store = transaction.objectStore('requests');
|
| 289 |
+
await store.add(requestData);
|
| 290 |
+
}
|
| 291 |
+
|
| 292 |
+
async function syncSecurityData() {
|
| 293 |
+
const db = await openDB();
|
| 294 |
+
const transaction = db.transaction(['requests'], 'readonly');
|
| 295 |
+
const store = transaction.objectStore('requests');
|
| 296 |
+
const requests = await store.getAll();
|
| 297 |
+
|
| 298 |
+
for (const requestData of requests) {
|
| 299 |
+
try {
|
| 300 |
+
await fetch(requestData.url, {
|
| 301 |
+
method: requestData.method,
|
| 302 |
+
headers: requestData.headers,
|
| 303 |
+
body: requestData.body
|
| 304 |
+
});
|
| 305 |
+
|
| 306 |
+
// Remove successfully synced request
|
| 307 |
+
const deleteTransaction = db.transaction(['requests'], 'readwrite');
|
| 308 |
+
const deleteStore = deleteTransaction.objectStore('requests');
|
| 309 |
+
await deleteStore.delete(requestData.timestamp);
|
| 310 |
+
|
| 311 |
+
} catch (error) {
|
| 312 |
+
console.log('Sync failed for request:', requestData.url);
|
| 313 |
+
}
|
| 314 |
+
}
|
| 315 |
+
}
|
| 316 |
+
|
| 317 |
+
// IndexedDB helper
|
| 318 |
+
function openDB() {
|
| 319 |
+
return new Promise((resolve, reject) => {
|
| 320 |
+
const request = indexedDB.open('SecurityPlatformDB', 1);
|
| 321 |
+
request.onerror = () => reject(request.error);
|
| 322 |
+
request.onsuccess = () => resolve(request.result);
|
| 323 |
+
request.onupgradeneeded = (event) => {
|
| 324 |
+
const db = event.target.result;
|
| 325 |
+
if (!db.objectStoreNames.contains('requests')) {
|
| 326 |
+
db.createObjectStore('requests', { keyPath: 'timestamp' });
|
| 327 |
+
}
|
| 328 |
+
if (!db.objectStoreNames.contains('analysis')) {
|
| 329 |
+
db.createObjectStore('analysis', { keyPath: 'id' });
|
| 330 |
+
}
|
| 331 |
+
if (!db.objectStoreNames.contains('training')) {
|
| 332 |
+
db.createObjectStore('training', { keyPath: 'id' });
|
| 333 |
+
}
|
| 334 |
+
};
|
| 335 |
+
});
|
| 336 |
+
}
|
| 337 |
+
|
| 338 |
+
console.log('🛡️ Service Worker loaded and ready');
|
| 339 |
+
`;
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
async setupOfflineCapabilities() {
|
| 343 |
+
// Pre-cache critical resources
|
| 344 |
+
await this.preCacheResources();
|
| 345 |
+
|
| 346 |
+
// Setup offline detection
|
| 347 |
+
this.setupOfflineDetection();
|
| 348 |
+
|
| 349 |
+
// Setup data synchronization
|
| 350 |
+
this.setupDataSynchronization();
|
| 351 |
+
}
|
| 352 |
+
|
| 353 |
+
async preCacheResources() {
|
| 354 |
+
if ('caches' in window) {
|
| 355 |
+
try {
|
| 356 |
+
const cache = await caches.open(this.cacheNames.static);
|
| 357 |
+
const criticalResources = [
|
| 358 |
+
'./',
|
| 359 |
+
'./advanced-security-platform.html',
|
| 360 |
+
'./styles/main.css',
|
| 361 |
+
'./js/ai-threat-analyzer.js',
|
| 362 |
+
'./js/real-time-monitor.js',
|
| 363 |
+
'./js/security-dashboard.js'
|
| 364 |
+
];
|
| 365 |
+
|
| 366 |
+
await cache.addAll(criticalResources);
|
| 367 |
+
console.log('📦 Critical resources cached for offline use');
|
| 368 |
+
|
| 369 |
+
} catch (error) {
|
| 370 |
+
console.warn('Failed to pre-cache resources:', error);
|
| 371 |
+
}
|
| 372 |
+
}
|
| 373 |
+
}
|
| 374 |
+
|
| 375 |
+
setupOfflineDetection() {
|
| 376 |
+
window.addEventListener('online', () => {
|
| 377 |
+
console.log('🌐 Back online - syncing data');
|
| 378 |
+
this.syncQueuedData();
|
| 379 |
+
this.showOnlineStatus();
|
| 380 |
+
});
|
| 381 |
+
|
| 382 |
+
window.addEventListener('offline', () => {
|
| 383 |
+
console.log('📱 Gone offline - enabling offline mode');
|
| 384 |
+
this.showOfflineStatus();
|
| 385 |
+
});
|
| 386 |
+
|
| 387 |
+
// Initial status check
|
| 388 |
+
if (!navigator.onLine) {
|
| 389 |
+
this.showOfflineStatus();
|
| 390 |
+
}
|
| 391 |
+
}
|
| 392 |
+
|
| 393 |
+
async setupBackgroundSync() {
|
| 394 |
+
if ('serviceWorker' in navigator && 'sync' in window.ServiceWorkerRegistration.prototype) {
|
| 395 |
+
try {
|
| 396 |
+
// Register background sync
|
| 397 |
+
const registration = await navigator.serviceWorker.ready;
|
| 398 |
+
await registration.sync.register('security-analysis-sync');
|
| 399 |
+
this.backgroundSync = true;
|
| 400 |
+
console.log('🔄 Background sync enabled');
|
| 401 |
+
|
| 402 |
+
} catch (error) {
|
| 403 |
+
console.warn('Background sync not available:', error);
|
| 404 |
+
}
|
| 405 |
+
} else {
|
| 406 |
+
console.log('⚠️ Background sync not supported');
|
| 407 |
+
}
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
async setupPushNotifications() {
|
| 411 |
+
if ('serviceWorker' in navigator && 'PushManager' in window) {
|
| 412 |
+
try {
|
| 413 |
+
const permission = await Notification.requestPermission();
|
| 414 |
+
if (permission === 'granted') {
|
| 415 |
+
const registration = await navigator.serviceWorker.ready;
|
| 416 |
+
const subscription = await registration.pushManager.subscribe({
|
| 417 |
+
userVisibleOnly: true,
|
| 418 |
+
applicationServerKey: this.urlBase64ToUint8Array(this.generateVapidKey())
|
| 419 |
+
});
|
| 420 |
+
|
| 421 |
+
this.pushNotifications = true;
|
| 422 |
+
console.log('📱 Push notifications enabled');
|
| 423 |
+
|
| 424 |
+
// Store subscription for later use
|
| 425 |
+
await this.storePushSubscription(subscription);
|
| 426 |
+
}
|
| 427 |
+
} catch (error) {
|
| 428 |
+
console.warn('Push notifications not available:', error);
|
| 429 |
+
}
|
| 430 |
+
}
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
urlBase64ToUint8Array(base64String) {
|
| 434 |
+
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
| 435 |
+
const base64 = (base64String + padding)
|
| 436 |
+
.replace(/-/g, '+')
|
| 437 |
+
.replace(/_/g, '/');
|
| 438 |
+
|
| 439 |
+
const rawData = window.atob(base64);
|
| 440 |
+
const outputArray = new Uint8Array(rawData.length);
|
| 441 |
+
|
| 442 |
+
for (let i = 0; i < rawData.length; ++i) {
|
| 443 |
+
outputArray[i] = rawData.charCodeAt(i);
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
return outputArray;
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
generateVapidKey() {
|
| 450 |
+
// In production, use actual VAPID keys
|
| 451 |
+
return 'BEl62iUYgUivxIkv69yViEuiBIa40HI80NQD9Fk4bQGjPU6u8F6c-cl9KCdCq3r5v5n8g5n3k2_3k1J7N5K2P5K3L8K9';
|
| 452 |
+
}
|
| 453 |
+
|
| 454 |
+
async storePushSubscription(subscription) {
|
| 455 |
+
// Store subscription in IndexedDB or send to server
|
| 456 |
+
try {
|
| 457 |
+
const db = await this.openIndexedDB();
|
| 458 |
+
const transaction = db.transaction(['subscriptions'], 'readwrite');
|
| 459 |
+
const store = transaction.objectStore('subscriptions');
|
| 460 |
+
await store.put({
|
| 461 |
+
id: 'main',
|
| 462 |
+
subscription: subscription,
|
| 463 |
+
timestamp: Date.now()
|
| 464 |
+
});
|
| 465 |
+
console.log('📱 Push subscription stored');
|
| 466 |
+
} catch (error) {
|
| 467 |
+
console.warn('Failed to store push subscription:', error);
|
| 468 |
+
}
|
| 469 |
+
}
|
| 470 |
+
|
| 471 |
+
async setupDataPersistence() {
|
| 472 |
+
// Setup IndexedDB for large data storage
|
| 473 |
+
this.db = await this.openIndexedDB();
|
| 474 |
+
|
| 475 |
+
// Setup data cleanup
|
| 476 |
+
this.scheduleDataCleanup();
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
async openIndexedDB() {
|
| 480 |
+
return new Promise((resolve, reject) => {
|
| 481 |
+
const request = indexedDB.open('SecurityPlatformDB', 1);
|
| 482 |
+
request.onerror = () => reject(request.error);
|
| 483 |
+
request.onsuccess = () => resolve(request.result);
|
| 484 |
+
request.onupgradeneeded = (event) => {
|
| 485 |
+
const db = event.target.result;
|
| 486 |
+
|
| 487 |
+
// Create object stores
|
| 488 |
+
if (!db.objectStoreNames.contains('analysis')) {
|
| 489 |
+
db.createObjectStore('analysis', { keyPath: 'id' });
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
if (!db.objectStoreNames.contains('training')) {
|
| 493 |
+
db.createObjectStore('training', { keyPath: 'id' });
|
| 494 |
+
}
|
| 495 |
+
|
| 496 |
+
if (!db.objectStoreNames.contains('threats')) {
|
| 497 |
+
db.createObjectStore('threats', { keyPath: 'id' });
|
| 498 |
+
}
|
| 499 |
+
|
| 500 |
+
if (!db.objectStoreNames.contains('logs')) {
|
| 501 |
+
db.createObjectStore('logs', { keyPath: 'id' });
|
| 502 |
+
}
|
| 503 |
+
|
| 504 |
+
if (!db.objectStoreNames.contains('subscriptions')) {
|
| 505 |
+
db.createObjectStore('subscriptions', { keyPath: 'id' });
|
| 506 |
+
}
|
| 507 |
+
};
|
| 508 |
+
});
|
| 509 |
+
}
|
| 510 |
+
|
| 511 |
+
setupInstallPrompt() {
|
| 512 |
+
let deferredPrompt = null;
|
| 513 |
+
|
| 514 |
+
window.addEventListener('beforeinstallprompt', (e) => {
|
| 515 |
+
console.log('💾 PWA install prompt available');
|
| 516 |
+
e.preventDefault();
|
| 517 |
+
deferredPrompt = e;
|
| 518 |
+
this.installPrompt = e;
|
| 519 |
+
|
| 520 |
+
// Show custom install button
|
| 521 |
+
this.showInstallButton();
|
| 522 |
+
});
|
| 523 |
+
|
| 524 |
+
window.addEventListener('appinstalled', () => {
|
| 525 |
+
console.log('📱 PWA installed successfully');
|
| 526 |
+
deferredPrompt = null;
|
| 527 |
+
this.hideInstallButton();
|
| 528 |
+
});
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
showInstallButton() {
|
| 532 |
+
// Create and show install button
|
| 533 |
+
const installButton = document.createElement('button');
|
| 534 |
+
installButton.id = 'pwa-install-button';
|
| 535 |
+
installButton.innerHTML = '📱 تثبيت التطبيق';
|
| 536 |
+
installButton.style.cssText = `
|
| 537 |
+
position: fixed;
|
| 538 |
+
bottom: 20px;
|
| 539 |
+
right: 20px;
|
| 540 |
+
background: #00e0d5;
|
| 541 |
+
color: white;
|
| 542 |
+
border: none;
|
| 543 |
+
padding: 12px 20px;
|
| 544 |
+
border-radius: 25px;
|
| 545 |
+
font-size: 14px;
|
| 546 |
+
font-weight: bold;
|
| 547 |
+
cursor: pointer;
|
| 548 |
+
box-shadow: 0 4px 12px rgba(0, 224, 213, 0.3);
|
| 549 |
+
z-index: 1000;
|
| 550 |
+
transition: all 0.3s ease;
|
| 551 |
+
`;
|
| 552 |
+
|
| 553 |
+
installButton.addEventListener('click', async () => {
|
| 554 |
+
if (this.installPrompt) {
|
| 555 |
+
this.installPrompt.prompt();
|
| 556 |
+
const { outcome } = await this.installPrompt.userChoice;
|
| 557 |
+
|
| 558 |
+
if (outcome === 'accepted') {
|
| 559 |
+
console.log('✅ PWA installation accepted');
|
| 560 |
+
} else {
|
| 561 |
+
console.log('❌ PWA installation dismissed');
|
| 562 |
+
}
|
| 563 |
+
|
| 564 |
+
this.installPrompt = null;
|
| 565 |
+
this.hideInstallButton();
|
| 566 |
+
}
|
| 567 |
+
});
|
| 568 |
+
|
| 569 |
+
document.body.appendChild(installButton);
|
| 570 |
+
}
|
| 571 |
+
|
| 572 |
+
hideInstallButton() {
|
| 573 |
+
const installButton = document.getElementById('pwa-install-button');
|
| 574 |
+
if (installButton) {
|
| 575 |
+
installButton.remove();
|
| 576 |
+
}
|
| 577 |
+
}
|
| 578 |
+
|
| 579 |
+
showOnlineStatus() {
|
| 580 |
+
this.showStatusMessage('🌐 الاتصال restored', 'success');
|
| 581 |
+
}
|
| 582 |
+
|
| 583 |
+
showOfflineStatus() {
|
| 584 |
+
this.showStatusMessage('📱 يعمل دون اتصال', 'warning');
|
| 585 |
+
}
|
| 586 |
+
|
| 587 |
+
showStatusMessage(message, type) {
|
| 588 |
+
const statusDiv = document.createElement('div');
|
| 589 |
+
statusDiv.className = `status-message status-${type}`;
|
| 590 |
+
statusDiv.textContent = message;
|
| 591 |
+
statusDiv.style.cssText = `
|
| 592 |
+
position: fixed;
|
| 593 |
+
top: 20px;
|
| 594 |
+
left: 50%;
|
| 595 |
+
transform: translateX(-50%);
|
| 596 |
+
background: ${type === 'success' ? '#4CAF50' : '#FF9800'};
|
| 597 |
+
color: white;
|
| 598 |
+
padding: 10px 20px;
|
| 599 |
+
border-radius: 5px;
|
| 600 |
+
z-index: 1001;
|
| 601 |
+
font-size: 14px;
|
| 602 |
+
font-weight: bold;
|
| 603 |
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
| 604 |
+
`;
|
| 605 |
+
|
| 606 |
+
document.body.appendChild(statusDiv);
|
| 607 |
+
|
| 608 |
+
setTimeout(() => {
|
| 609 |
+
statusDiv.remove();
|
| 610 |
+
}, 3000);
|
| 611 |
+
}
|
| 612 |
+
|
| 613 |
+
showUpdateAvailable() {
|
| 614 |
+
const updateDiv = document.createElement('div');
|
| 615 |
+
updateDiv.innerHTML = `
|
| 616 |
+
<div style="background: #2196F3; color: white; padding: 15px; text-align: center; position: fixed; top: 0; left: 0; right: 0; z-index: 1002;">
|
| 617 |
+
<strong>🚀 تحديث جديد متوفر</strong>
|
| 618 |
+
<button onclick="window.location.reload()" style="margin-left: 10px; padding: 5px 15px; background: white; color: #2196F3; border: none; border-radius: 3px; cursor: pointer;">تحديث الآن</button>
|
| 619 |
+
</div>
|
| 620 |
+
`;
|
| 621 |
+
document.body.appendChild(updateDiv);
|
| 622 |
+
}
|
| 623 |
+
|
| 624 |
+
// Data management methods
|
| 625 |
+
async storeAnalysisData(data) {
|
| 626 |
+
try {
|
| 627 |
+
const transaction = this.db.transaction(['analysis'], 'readwrite');
|
| 628 |
+
const store = transaction.objectStore('analysis');
|
| 629 |
+
|
| 630 |
+
const analysisRecord = {
|
| 631 |
+
id: 'analysis_' + Date.now(),
|
| 632 |
+
data: data,
|
| 633 |
+
timestamp: Date.now(),
|
| 634 |
+
synced: false
|
| 635 |
+
};
|
| 636 |
+
|
| 637 |
+
await store.add(analysisRecord);
|
| 638 |
+
this.offlineData.set(analysisRecord.id, analysisRecord);
|
| 639 |
+
|
| 640 |
+
console.log('💾 Analysis data stored offline');
|
| 641 |
+
|
| 642 |
+
} catch (error) {
|
| 643 |
+
console.error('Failed to store analysis data:', error);
|
| 644 |
+
}
|
| 645 |
+
}
|
| 646 |
+
|
| 647 |
+
async getAnalysisData() {
|
| 648 |
+
try {
|
| 649 |
+
const transaction = this.db.transaction(['analysis'], 'readonly');
|
| 650 |
+
const store = transaction.objectStore('analysis');
|
| 651 |
+
const data = await store.getAll();
|
| 652 |
+
|
| 653 |
+
return data.map(record => record.data);
|
| 654 |
+
|
| 655 |
+
} catch (error) {
|
| 656 |
+
console.error('Failed to retrieve analysis data:', error);
|
| 657 |
+
return [];
|
| 658 |
+
}
|
| 659 |
+
}
|
| 660 |
+
|
| 661 |
+
async storeTrainingProgress(progress) {
|
| 662 |
+
try {
|
| 663 |
+
const transaction = this.db.transaction(['training'], 'readwrite');
|
| 664 |
+
const store = transaction.objectStore('training');
|
| 665 |
+
|
| 666 |
+
const progressRecord = {
|
| 667 |
+
id: 'progress_' + Date.now(),
|
| 668 |
+
progress: progress,
|
| 669 |
+
timestamp: Date.now(),
|
| 670 |
+
synced: false
|
| 671 |
+
};
|
| 672 |
+
|
| 673 |
+
await store.add(progressRecord);
|
| 674 |
+
this.syncQueue.push(progressRecord);
|
| 675 |
+
|
| 676 |
+
console.log('📚 Training progress stored offline');
|
| 677 |
+
|
| 678 |
+
} catch (error) {
|
| 679 |
+
console.error('Failed to store training progress:', error);
|
| 680 |
+
}
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
async syncQueuedData() {
|
| 684 |
+
if (!navigator.onLine || this.syncQueue.length === 0) {
|
| 685 |
+
return;
|
| 686 |
+
}
|
| 687 |
+
|
| 688 |
+
console.log('🔄 Syncing queued data...');
|
| 689 |
+
|
| 690 |
+
for (const item of this.syncQueue) {
|
| 691 |
+
try {
|
| 692 |
+
// Simulate sync operation
|
| 693 |
+
await this.syncItem(item);
|
| 694 |
+
console.log('✅ Synced item:', item.id);
|
| 695 |
+
} catch (error) {
|
| 696 |
+
console.error('Failed to sync item:', item.id, error);
|
| 697 |
+
}
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
this.syncQueue = [];
|
| 701 |
+
}
|
| 702 |
+
|
| 703 |
+
async syncItem(item) {
|
| 704 |
+
// Simulate API call
|
| 705 |
+
return new Promise((resolve) => {
|
| 706 |
+
setTimeout(resolve, 1000);
|
| 707 |
+
});
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
setupDataSynchronization() {
|
| 711 |
+
// Auto-sync every 5 minutes when online
|
| 712 |
+
setInterval(() => {
|
| 713 |
+
if (navigator.onLine) {
|
| 714 |
+
this.syncQueuedData();
|
| 715 |
+
}
|
| 716 |
+
}, 5 * 60 * 1000);
|
| 717 |
+
}
|
| 718 |
+
|
| 719 |
+
scheduleDataCleanup() {
|
| 720 |
+
// Clean up old data every hour
|
| 721 |
+
setInterval(() => {
|
| 722 |
+
this.cleanupOldData();
|
| 723 |
+
}, 60 * 60 * 1000);
|
| 724 |
+
}
|
| 725 |
+
|
| 726 |
+
async cleanupOldData() {
|
| 727 |
+
try {
|
| 728 |
+
const cutoffTime = Date.now() - (7 * 24 * 60 * 60 * 1000); // 7 days ago
|
| 729 |
+
|
| 730 |
+
const stores = ['analysis', 'training', 'logs'];
|
| 731 |
+
|
| 732 |
+
for (const storeName of stores) {
|
| 733 |
+
const transaction = this.db.transaction([storeName], 'readwrite');
|
| 734 |
+
const store = transaction.objectStore(storeName);
|
| 735 |
+
const data = await store.getAll();
|
| 736 |
+
|
| 737 |
+
for (const item of data) {
|
| 738 |
+
if (item.timestamp < cutoffTime) {
|
| 739 |
+
await store.delete(item.id);
|
| 740 |
+
}
|
| 741 |
+
}
|
| 742 |
+
}
|
| 743 |
+
|
| 744 |
+
console.log('🧹 Old data cleaned up');
|
| 745 |
+
|
| 746 |
+
} catch (error) {
|
| 747 |
+
console.error('Failed to cleanup old data:', error);
|
| 748 |
+
}
|
| 749 |
+
}
|
| 750 |
+
|
| 751 |
+
fallbackToLocalStorage() {
|
| 752 |
+
console.log('⚠️ Using localStorage fallback');
|
| 753 |
+
|
| 754 |
+
// Use localStorage for basic persistence
|
| 755 |
+
this.storeInLocalStorage = (key, data) => {
|
| 756 |
+
localStorage.setItem(key, JSON.stringify(data));
|
| 757 |
+
};
|
| 758 |
+
|
| 759 |
+
this.getFromLocalStorage = (key) => {
|
| 760 |
+
const data = localStorage.getItem(key);
|
| 761 |
+
return data ? JSON.parse(data) : null;
|
| 762 |
+
};
|
| 763 |
+
}
|
| 764 |
+
|
| 765 |
+
// Public API methods
|
| 766 |
+
async sendNotification(title, body, actions = []) {
|
| 767 |
+
if (!this.pushNotifications) {
|
| 768 |
+
console.warn('Push notifications not available');
|
| 769 |
+
return;
|
| 770 |
+
}
|
| 771 |
+
|
| 772 |
+
try {
|
| 773 |
+
const registration = await navigator.serviceWorker.ready;
|
| 774 |
+
await registration.showNotification(title, {
|
| 775 |
+
body: body,
|
| 776 |
+
icon: '/icon-192x192.png',
|
| 777 |
+
badge: '/badge-72x72.png',
|
| 778 |
+
tag: 'security-platform',
|
| 779 |
+
actions: actions,
|
| 780 |
+
requireInteraction: true
|
| 781 |
+
});
|
| 782 |
+
} catch (error) {
|
| 783 |
+
console.error('Failed to send notification:', error);
|
| 784 |
+
}
|
| 785 |
+
}
|
| 786 |
+
|
| 787 |
+
isOnline() {
|
| 788 |
+
return navigator.onLine;
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
getCacheStatus() {
|
| 792 |
+
return {
|
| 793 |
+
static: this.cacheNames.static,
|
| 794 |
+
dynamic: this.cacheNames.dynamic,
|
| 795 |
+
api: this.cacheNames.api,
|
| 796 |
+
backgroundSync: this.backgroundSync,
|
| 797 |
+
pushNotifications: this.pushNotifications,
|
| 798 |
+
offlineDataCount: this.offlineData.size
|
| 799 |
+
};
|
| 800 |
+
}
|
| 801 |
+
|
| 802 |
+
async clearCache() {
|
| 803 |
+
if ('caches' in window) {
|
| 804 |
+
const cacheNames = Object.values(this.cacheNames);
|
| 805 |
+
await Promise.all(cacheNames.map(name => caches.delete(name)));
|
| 806 |
+
console.log('🗑️ Cache cleared');
|
| 807 |
+
}
|
| 808 |
+
}
|
| 809 |
+
|
| 810 |
+
dispose() {
|
| 811 |
+
if (this.registration) {
|
| 812 |
+
this.registration.unregister();
|
| 813 |
+
}
|
| 814 |
+
}
|
| 815 |
+
}
|
| 816 |
+
|
| 817 |
+
// Export for use in other modules
|
| 818 |
+
if (typeof module !== 'undefined' && module.exports) {
|
| 819 |
+
module.exports = { ServiceWorkerManager };
|
| 820 |
+
}
|
js/smart-policy-generator.js
ADDED
|
@@ -0,0 +1,1036 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/**
|
| 2 |
+
* مولد السياسات التلقائي الذكي
|
| 3 |
+
* Smart Auto-Policy Generator
|
| 4 |
+
* Intelligent CSP and security policy generation system
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
class SmartPolicyGenerator {
|
| 8 |
+
constructor() {
|
| 9 |
+
this.policyTemplates = {
|
| 10 |
+
basic: {
|
| 11 |
+
name: 'الأساسي',
|
| 12 |
+
description: 'سياسة أمان أساسية للمواقع البسيطة',
|
| 13 |
+
csp: "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self';",
|
| 14 |
+
headers: {
|
| 15 |
+
'X-Content-Type-Options': 'nosniff',
|
| 16 |
+
'X-Frame-Options': 'DENY',
|
| 17 |
+
'X-XSS-Protection': '1; mode=block'
|
| 18 |
+
}
|
| 19 |
+
},
|
| 20 |
+
strict: {
|
| 21 |
+
name: 'صارم',
|
| 22 |
+
description: 'سياسة أمان صارمة للتطبيقات الحساسة',
|
| 23 |
+
csp: "default-src 'none'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';",
|
| 24 |
+
headers: {
|
| 25 |
+
'Content-Security-Policy': '',
|
| 26 |
+
'X-Content-Type-Options': 'nosniff',
|
| 27 |
+
'X-Frame-Options': 'DENY',
|
| 28 |
+
'X-XSS-Protection': '1; mode=block',
|
| 29 |
+
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
|
| 30 |
+
'Referrer-Policy': 'strict-origin-when-cross-origin'
|
| 31 |
+
}
|
| 32 |
+
},
|
| 33 |
+
modern: {
|
| 34 |
+
name: 'حديث',
|
| 35 |
+
description: 'سياسة حديثة مع Trusted Types و strict-dynamic',
|
| 36 |
+
csp: "default-src 'self'; script-src 'self' 'strict-dynamic' 'nonce-{random}'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; require-trusted-types-for 'script';",
|
| 37 |
+
headers: {
|
| 38 |
+
'Content-Security-Policy': '',
|
| 39 |
+
'X-Content-Type-Options': 'nosniff',
|
| 40 |
+
'X-Frame-Options': 'DENY',
|
| 41 |
+
'Cross-Origin-Opener-Policy': 'same-origin',
|
| 42 |
+
'Cross-Origin-Embedder-Policy': 'require-corp',
|
| 43 |
+
'Cross-Origin-Resource-Policy': 'same-origin'
|
| 44 |
+
}
|
| 45 |
+
},
|
| 46 |
+
ecommerce: {
|
| 47 |
+
name: 'التجارة الإلكترونية',
|
| 48 |
+
description: 'سياسة مخصصة للمتاجر الإلكترونية',
|
| 49 |
+
csp: "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https:; frame-ancestors 'none'; base-uri 'self'; form-action 'self' https:;",
|
| 50 |
+
headers: {
|
| 51 |
+
'Content-Security-Policy': '',
|
| 52 |
+
'X-Content-Type-Options': 'nosniff',
|
| 53 |
+
'X-Frame-Options': 'DENY',
|
| 54 |
+
'X-XSS-Protection': '1; mode=block',
|
| 55 |
+
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
|
| 56 |
+
'Referrer-Policy': 'strict-origin-when-cross-origin'
|
| 57 |
+
}
|
| 58 |
+
},
|
| 59 |
+
saas: {
|
| 60 |
+
name: 'تطبيق SaaS',
|
| 61 |
+
description: 'سياسة لتطبيقات البرمجيات كخدمة',
|
| 62 |
+
csp: "default-src 'self'; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com; connect-src 'self' https: wss:; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; worker-src 'self';",
|
| 63 |
+
headers: {
|
| 64 |
+
'Content-Security-Policy': '',
|
| 65 |
+
'X-Content-Type-Options': 'nosniff',
|
| 66 |
+
'X-Frame-Options': 'DENY',
|
| 67 |
+
'Cross-Origin-Opener-Policy': 'same-origin',
|
| 68 |
+
'Cross-Origin-Embedder-Policy': 'require-corp',
|
| 69 |
+
'Referrer-Policy': 'strict-origin-when-cross-origin'
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
};
|
| 73 |
+
|
| 74 |
+
this.analyzer = new AIThreatAnalyzer();
|
| 75 |
+
this.userPreferences = this.loadUserPreferences();
|
| 76 |
+
this.learningData = this.loadLearningData();
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
/**
|
| 80 |
+
* تحليل الموقع وتوليد السياسة المناسبة
|
| 81 |
+
* Analyze website and generate appropriate policy
|
| 82 |
+
*/
|
| 83 |
+
async generatePolicy(websiteUrl, options = {}) {
|
| 84 |
+
try {
|
| 85 |
+
// تحليل الموقع
|
| 86 |
+
const analysis = await this.analyzeWebsite(websiteUrl);
|
| 87 |
+
|
| 88 |
+
// تحديد نوع الموقع
|
| 89 |
+
const websiteType = this.classifyWebsiteType(analysis);
|
| 90 |
+
|
| 91 |
+
// توليد السياسة الأساسية
|
| 92 |
+
let basePolicy = this.getBasePolicy(websiteType, options.strictness);
|
| 93 |
+
|
| 94 |
+
// تخصيص السياسة بناءً على التحليل
|
| 95 |
+
const customizedPolicy = this.customizePolicy(basePolicy, analysis, options);
|
| 96 |
+
|
| 97 |
+
// تحسين السياسة
|
| 98 |
+
const optimizedPolicy = this.optimizePolicy(customizedPolicy, analysis);
|
| 99 |
+
|
| 100 |
+
// إضافة التوصيات
|
| 101 |
+
const finalPolicy = this.addRecommendations(optimizedPolicy, analysis);
|
| 102 |
+
|
| 103 |
+
return {
|
| 104 |
+
websiteUrl,
|
| 105 |
+
websiteType,
|
| 106 |
+
analysis,
|
| 107 |
+
policy: finalPolicy,
|
| 108 |
+
recommendations: this.generateImplementationRecommendations(finalPolicy),
|
| 109 |
+
implementation: this.generateImplementationGuide(finalPolicy),
|
| 110 |
+
timestamp: new Date().toISOString()
|
| 111 |
+
};
|
| 112 |
+
|
| 113 |
+
} catch (error) {
|
| 114 |
+
console.error('خطأ في توليد السياسة:', error);
|
| 115 |
+
throw new Error(`فشل في توليد السياسة: ${error.message}`);
|
| 116 |
+
}
|
| 117 |
+
}
|
| 118 |
+
|
| 119 |
+
/**
|
| 120 |
+
* تحليل الموقع
|
| 121 |
+
* Analyze website
|
| 122 |
+
*/
|
| 123 |
+
async analyzeWebsite(url) {
|
| 124 |
+
const analysis = {
|
| 125 |
+
url,
|
| 126 |
+
technologies: [],
|
| 127 |
+
externalResources: [],
|
| 128 |
+
securityHeaders: {},
|
| 129 |
+
scripts: [],
|
| 130 |
+
styles: [],
|
| 131 |
+
images: [],
|
| 132 |
+
forms: [],
|
| 133 |
+
iframes: [],
|
| 134 |
+
metaTags: [],
|
| 135 |
+
javascriptFeatures: []
|
| 136 |
+
};
|
| 137 |
+
|
| 138 |
+
try {
|
| 139 |
+
// محاكاة تحليل الموقع (في التطبيق الحقيقي، ستحتاج API أو web scraping)
|
| 140 |
+
analysis.technologies = await this.detectTechnologies(url);
|
| 141 |
+
analysis.externalResources = await this.scanExternalResources(url);
|
| 142 |
+
analysis.securityHeaders = await this.checkSecurityHeaders(url);
|
| 143 |
+
analysis.scripts = await this.scanScripts(url);
|
| 144 |
+
analysis.styles = await this.scanStyles(url);
|
| 145 |
+
analysis.images = await this.scanImages(url);
|
| 146 |
+
analysis.forms = await this.scanForms(url);
|
| 147 |
+
analysis.iframes = await this.scanIframes(url);
|
| 148 |
+
analysis.metaTags = await this.scanMetaTags(url);
|
| 149 |
+
analysis.javascriptFeatures = await this.detectJavaScriptFeatures(url);
|
| 150 |
+
|
| 151 |
+
} catch (error) {
|
| 152 |
+
console.warn('تحليل جزئي للموقع:', error);
|
| 153 |
+
// في حالة الفشل، نستخدم تحليل افتراضي
|
| 154 |
+
analysis.technologies = ['HTML5', 'CSS3', 'JavaScript'];
|
| 155 |
+
analysis.externalResources = [];
|
| 156 |
+
analysis.securityHeaders = {};
|
| 157 |
+
}
|
| 158 |
+
|
| 159 |
+
return analysis;
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
/**
|
| 163 |
+
* اكتشاف التقنيات المستخدمة
|
| 164 |
+
* Detect used technologies
|
| 165 |
+
*/
|
| 166 |
+
async detectTechnologies(url) {
|
| 167 |
+
const technologies = [];
|
| 168 |
+
|
| 169 |
+
try {
|
| 170 |
+
// فحص React
|
| 171 |
+
if (window.React || document.querySelector('[data-reactroot]')) {
|
| 172 |
+
technologies.push('React');
|
| 173 |
+
}
|
| 174 |
+
|
| 175 |
+
// فحص Vue.js
|
| 176 |
+
if (window.Vue || document.querySelector('[v-cloak]')) {
|
| 177 |
+
technologies.push('Vue.js');
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
// فحص Angular
|
| 181 |
+
if (window.angular || document.querySelector('[ng-app]')) {
|
| 182 |
+
technologies.push('Angular');
|
| 183 |
+
}
|
| 184 |
+
|
| 185 |
+
// فحص jQuery
|
| 186 |
+
if (window.jQuery || window.$) {
|
| 187 |
+
technologies.push('jQuery');
|
| 188 |
+
}
|
| 189 |
+
|
| 190 |
+
// فحص Bootstrap
|
| 191 |
+
if (window.bootstrap || document.querySelector('.btn-primary')) {
|
| 192 |
+
technologies.push('Bootstrap');
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
// فحص TypeScript
|
| 196 |
+
if (document.querySelector('script[type="module"]') || window.TypeScript) {
|
| 197 |
+
technologies.push('TypeScript');
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
} catch (error) {
|
| 201 |
+
console.warn('خطأ في اكتشاف التقنيات:', error);
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
return technologies.length > 0 ? technologies : ['HTML5', 'CSS3', 'JavaScript'];
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
/**
|
| 208 |
+
* فحص الموارد الخارجية
|
| 209 |
+
* Scan external resources
|
| 210 |
+
*/
|
| 211 |
+
async scanExternalResources(url) {
|
| 212 |
+
const resources = {
|
| 213 |
+
scripts: [],
|
| 214 |
+
styles: [],
|
| 215 |
+
images: [],
|
| 216 |
+
fonts: []
|
| 217 |
+
};
|
| 218 |
+
|
| 219 |
+
try {
|
| 220 |
+
// فحص العناصر في DOM
|
| 221 |
+
document.querySelectorAll('script[src]').forEach(script => {
|
| 222 |
+
const src = script.src;
|
| 223 |
+
if (src.startsWith('http') && !src.includes(new URL(url).hostname)) {
|
| 224 |
+
resources.scripts.push({
|
| 225 |
+
src,
|
| 226 |
+
integrity: script.integrity || null,
|
| 227 |
+
crossorigin: script.crossOrigin || null
|
| 228 |
+
});
|
| 229 |
+
}
|
| 230 |
+
});
|
| 231 |
+
|
| 232 |
+
document.querySelectorAll('link[href]').forEach(link => {
|
| 233 |
+
const href = link.href;
|
| 234 |
+
if (href.startsWith('http') && !href.includes(new URL(url).hostname)) {
|
| 235 |
+
if (link.rel === 'stylesheet') {
|
| 236 |
+
resources.styles.push({
|
| 237 |
+
href,
|
| 238 |
+
integrity: link.integrity || null,
|
| 239 |
+
crossorigin: link.crossOrigin || null
|
| 240 |
+
});
|
| 241 |
+
} else if (link.rel.includes('icon') || link.rel.includes('apple-touch-icon')) {
|
| 242 |
+
resources.images.push({ href });
|
| 243 |
+
} else if (link.rel === 'preload' && link.as === 'font') {
|
| 244 |
+
resources.fonts.push({ href });
|
| 245 |
+
}
|
| 246 |
+
}
|
| 247 |
+
});
|
| 248 |
+
|
| 249 |
+
document.querySelectorAll('img[src]').forEach(img => {
|
| 250 |
+
const src = img.src;
|
| 251 |
+
if (src.startsWith('http') && !src.includes(new URL(url).hostname)) {
|
| 252 |
+
resources.images.push({
|
| 253 |
+
src,
|
| 254 |
+
alt: img.alt || null
|
| 255 |
+
});
|
| 256 |
+
}
|
| 257 |
+
});
|
| 258 |
+
|
| 259 |
+
} catch (error) {
|
| 260 |
+
console.warn('خطأ في فحص الموارد الخارجية:', error);
|
| 261 |
+
}
|
| 262 |
+
|
| 263 |
+
return resources;
|
| 264 |
+
}
|
| 265 |
+
|
| 266 |
+
/**
|
| 267 |
+
* فحص رؤوس الأمان
|
| 268 |
+
* Check security headers
|
| 269 |
+
*/
|
| 270 |
+
async checkSecurityHeaders(url) {
|
| 271 |
+
const headers = {};
|
| 272 |
+
|
| 273 |
+
try {
|
| 274 |
+
// محاكاة فحص الرؤوس (في التطبيق الحقيقي تحتاج CORS proxy)
|
| 275 |
+
const response = await fetch(url, { method: 'HEAD' });
|
| 276 |
+
|
| 277 |
+
const securityHeaderNames = [
|
| 278 |
+
'Content-Security-Policy',
|
| 279 |
+
'X-Content-Type-Options',
|
| 280 |
+
'X-Frame-Options',
|
| 281 |
+
'X-XSS-Protection',
|
| 282 |
+
'Strict-Transport-Security',
|
| 283 |
+
'Referrer-Policy',
|
| 284 |
+
'Permissions-Policy',
|
| 285 |
+
'Cross-Origin-Opener-Policy',
|
| 286 |
+
'Cross-Origin-Embedder-Policy'
|
| 287 |
+
];
|
| 288 |
+
|
| 289 |
+
securityHeaderNames.forEach(headerName => {
|
| 290 |
+
const headerValue = response.headers.get(headerName);
|
| 291 |
+
if (headerValue) {
|
| 292 |
+
headers[headerName] = headerValue;
|
| 293 |
+
}
|
| 294 |
+
});
|
| 295 |
+
|
| 296 |
+
} catch (error) {
|
| 297 |
+
console.warn('خطأ في فحص رؤوس الأمان:', error);
|
| 298 |
+
// إرجاع قيم افتراضية بناءً على الموقع
|
| 299 |
+
headers['X-Content-Type-Options'] = 'nosniff';
|
| 300 |
+
}
|
| 301 |
+
|
| 302 |
+
return headers;
|
| 303 |
+
}
|
| 304 |
+
|
| 305 |
+
/**
|
| 306 |
+
* فحص السكريبت
|
| 307 |
+
* Scan scripts
|
| 308 |
+
*/
|
| 309 |
+
async scanScripts(url) {
|
| 310 |
+
const scripts = [];
|
| 311 |
+
|
| 312 |
+
try {
|
| 313 |
+
document.querySelectorAll('script').forEach(script => {
|
| 314 |
+
scripts.push({
|
| 315 |
+
src: script.src || null,
|
| 316 |
+
type: script.type || 'text/javascript',
|
| 317 |
+
async: script.async || false,
|
| 318 |
+
defer: script.defer || false,
|
| 319 |
+
nonce: script.nonce || null,
|
| 320 |
+
integrity: script.integrity || null,
|
| 321 |
+
hasInline: script.textContent.trim().length > 0,
|
| 322 |
+
lineCount: script.textContent.split('\n').length
|
| 323 |
+
});
|
| 324 |
+
});
|
| 325 |
+
} catch (error) {
|
| 326 |
+
console.warn('خطأ في فحص السكريبت:', error);
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
return scripts;
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
/**
|
| 333 |
+
* فحص الأنماط
|
| 334 |
+
* Scan styles
|
| 335 |
+
*/
|
| 336 |
+
async scanStyles(url) {
|
| 337 |
+
const styles = [];
|
| 338 |
+
|
| 339 |
+
try {
|
| 340 |
+
document.querySelectorAll('style').forEach(style => {
|
| 341 |
+
styles.push({
|
| 342 |
+
hasInline: style.textContent.trim().length > 0,
|
| 343 |
+
lineCount: style.textContent.split('\n').length
|
| 344 |
+
});
|
| 345 |
+
});
|
| 346 |
+
|
| 347 |
+
document.querySelectorAll('link[rel="stylesheet"]').forEach(link => {
|
| 348 |
+
styles.push({
|
| 349 |
+
href: link.href,
|
| 350 |
+
integrity: link.integrity || null,
|
| 351 |
+
crossorigin: link.crossOrigin || null
|
| 352 |
+
});
|
| 353 |
+
});
|
| 354 |
+
} catch (error) {
|
| 355 |
+
console.warn('خطأ في فحص الأنماط:', error);
|
| 356 |
+
}
|
| 357 |
+
|
| 358 |
+
return styles;
|
| 359 |
+
}
|
| 360 |
+
|
| 361 |
+
/**
|
| 362 |
+
* فحص الصور
|
| 363 |
+
* Scan images
|
| 364 |
+
*/
|
| 365 |
+
async scanImages(url) {
|
| 366 |
+
const images = [];
|
| 367 |
+
|
| 368 |
+
try {
|
| 369 |
+
document.querySelectorAll('img').forEach(img => {
|
| 370 |
+
images.push({
|
| 371 |
+
src: img.src,
|
| 372 |
+
alt: img.alt || null,
|
| 373 |
+
width: img.width || null,
|
| 374 |
+
height: img.height || null,
|
| 375 |
+
loading: img.loading || 'eager'
|
| 376 |
+
});
|
| 377 |
+
});
|
| 378 |
+
} catch (error) {
|
| 379 |
+
console.warn('خطأ في فحص ��لصور:', error);
|
| 380 |
+
}
|
| 381 |
+
|
| 382 |
+
return images;
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
/**
|
| 386 |
+
* فحص النماذج
|
| 387 |
+
* Scan forms
|
| 388 |
+
*/
|
| 389 |
+
async scanForms(url) {
|
| 390 |
+
const forms = [];
|
| 391 |
+
|
| 392 |
+
try {
|
| 393 |
+
document.querySelectorAll('form').forEach(form => {
|
| 394 |
+
forms.push({
|
| 395 |
+
action: form.action || null,
|
| 396 |
+
method: form.method || 'GET',
|
| 397 |
+
target: form.target || null,
|
| 398 |
+
hasCSRF: form.querySelector('input[name*="token"], input[name*="csrf"]') !== null,
|
| 399 |
+
inputs: Array.from(form.querySelectorAll('input')).map(input => ({
|
| 400 |
+
type: input.type,
|
| 401 |
+
name: input.name,
|
| 402 |
+
required: input.required
|
| 403 |
+
}))
|
| 404 |
+
});
|
| 405 |
+
});
|
| 406 |
+
} catch (error) {
|
| 407 |
+
console.warn('خطأ في فحص النماذج:', error);
|
| 408 |
+
}
|
| 409 |
+
|
| 410 |
+
return forms;
|
| 411 |
+
}
|
| 412 |
+
|
| 413 |
+
/**
|
| 414 |
+
* فحص الإطارات
|
| 415 |
+
* Scan iframes
|
| 416 |
+
*/
|
| 417 |
+
async scanIframes(url) {
|
| 418 |
+
const iframes = [];
|
| 419 |
+
|
| 420 |
+
try {
|
| 421 |
+
document.querySelectorAll('iframe').forEach(iframe => {
|
| 422 |
+
iframes.push({
|
| 423 |
+
src: iframe.src || null,
|
| 424 |
+
sandbox: iframe.sandbox || null,
|
| 425 |
+
width: iframe.width || null,
|
| 426 |
+
height: iframe.height || null
|
| 427 |
+
});
|
| 428 |
+
});
|
| 429 |
+
} catch (error) {
|
| 430 |
+
console.warn('خطأ في فحص الإطارات:', error);
|
| 431 |
+
}
|
| 432 |
+
|
| 433 |
+
return iframes;
|
| 434 |
+
}
|
| 435 |
+
|
| 436 |
+
/**
|
| 437 |
+
* فحص Meta Tags
|
| 438 |
+
* Scan meta tags
|
| 439 |
+
*/
|
| 440 |
+
async scanMetaTags(url) {
|
| 441 |
+
const metaTags = [];
|
| 442 |
+
|
| 443 |
+
try {
|
| 444 |
+
document.querySelectorAll('meta').forEach(meta => {
|
| 445 |
+
metaTags.push({
|
| 446 |
+
name: meta.name || meta.property || null,
|
| 447 |
+
content: meta.content || null,
|
| 448 |
+
httpEquiv: meta.httpEquiv || null
|
| 449 |
+
});
|
| 450 |
+
});
|
| 451 |
+
} catch (error) {
|
| 452 |
+
console.warn('خطأ في فحص Meta Tags:', error);
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
return metaTags;
|
| 456 |
+
}
|
| 457 |
+
|
| 458 |
+
/**
|
| 459 |
+
* اكتشاف ميزات JavaScript
|
| 460 |
+
* Detect JavaScript features
|
| 461 |
+
*/
|
| 462 |
+
async detectJavaScriptFeatures(url) {
|
| 463 |
+
const features = [];
|
| 464 |
+
|
| 465 |
+
try {
|
| 466 |
+
// فحص ميزات المتصفح
|
| 467 |
+
if ('fetch' in window) features.push('Fetch API');
|
| 468 |
+
if ('Promise' in window) features.push('Promises');
|
| 469 |
+
if ('localStorage' in window) features.push('LocalStorage');
|
| 470 |
+
if ('sessionStorage' in window) features.push('SessionStorage');
|
| 471 |
+
if ('WebSocket' in window) features.push('WebSocket');
|
| 472 |
+
if ('ServiceWorker' in window) features.push('ServiceWorker');
|
| 473 |
+
if ('WebRTC' in window) features.push('WebRTC');
|
| 474 |
+
if ('Notification' in window) features.push('Notifications');
|
| 475 |
+
if ('Notification' in window && 'permission' in Notification) {
|
| 476 |
+
const permission = Notification.permission;
|
| 477 |
+
if (permission === 'granted') features.push('Notifications (granted)');
|
| 478 |
+
else if (permission === 'denied') features.push('Notifications (denied)');
|
| 479 |
+
}
|
| 480 |
+
|
| 481 |
+
// فحص مكتبات معينة
|
| 482 |
+
if (window.jQuery) features.push('jQuery');
|
| 483 |
+
if (window.React) features.push('React');
|
| 484 |
+
if (window.Vue) features.push('Vue.js');
|
| 485 |
+
if (window.angular) features.push('Angular');
|
| 486 |
+
if (window.bootstrap) features.push('Bootstrap');
|
| 487 |
+
|
| 488 |
+
} catch (error) {
|
| 489 |
+
console.warn('خطأ في اكتشاف ميزات JavaScript:', error);
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
return features;
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
/**
|
| 496 |
+
* تصنيف نوع الموقع
|
| 497 |
+
* Classify website type
|
| 498 |
+
*/
|
| 499 |
+
classifyWebsiteType(analysis) {
|
| 500 |
+
const { technologies, scripts, forms, iframes, javascriptFeatures } = analysis;
|
| 501 |
+
|
| 502 |
+
// فحص مؤشرات التجارة الإلكترونية
|
| 503 |
+
if (forms.some(form => form.action && form.action.includes('checkout')) ||
|
| 504 |
+
scripts.some(script => script.src && script.src.includes('stripe')) ||
|
| 505 |
+
scripts.some(script => script.src && script.src.includes('paypal'))) {
|
| 506 |
+
return 'ecommerce';
|
| 507 |
+
}
|
| 508 |
+
|
| 509 |
+
// فحص مؤشرات SaaS
|
| 510 |
+
if (javascriptFeatures.includes('WebSocket') ||
|
| 511 |
+
javascriptFeatures.includes('ServiceWorker') ||
|
| 512 |
+
scripts.some(script => script.src && script.src.includes('api'))) {
|
| 513 |
+
return 'saas';
|
| 514 |
+
}
|
| 515 |
+
|
| 516 |
+
// فحص مؤشرات التطبيق التفاعلي
|
| 517 |
+
if (javascriptFeatures.includes('WebRTC') ||
|
| 518 |
+
technologies.includes('React') ||
|
| 519 |
+
technologies.includes('Vue.js') ||
|
| 520 |
+
technologies.includes('Angular')) {
|
| 521 |
+
return 'modern';
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
// فحص مؤشرات الموقع الأساسي
|
| 525 |
+
if (scripts.length === 0 && forms.length === 0 && iframes.length === 0) {
|
| 526 |
+
return 'basic';
|
| 527 |
+
}
|
| 528 |
+
|
| 529 |
+
// افتراضي
|
| 530 |
+
return 'modern';
|
| 531 |
+
}
|
| 532 |
+
|
| 533 |
+
/**
|
| 534 |
+
* الحصول على السياسة الأساسية
|
| 535 |
+
* Get base policy
|
| 536 |
+
*/
|
| 537 |
+
getBasePolicy(websiteType, strictness = 'medium') {
|
| 538 |
+
let template = this.policyTemplates[websiteType] || this.policyTemplates.basic;
|
| 539 |
+
|
| 540 |
+
if (strictness === 'high') {
|
| 541 |
+
template = this.policyTemplates.strict;
|
| 542 |
+
} else if (strictness === 'low') {
|
| 543 |
+
// تخفيف السياسة للصرامة المنخفضة
|
| 544 |
+
template = {
|
| 545 |
+
...template,
|
| 546 |
+
csp: template.csp.replace("'none'", "'self'").replace("'strict-dynamic'", "'unsafe-inline'")
|
| 547 |
+
};
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
return { ...template };
|
| 551 |
+
}
|
| 552 |
+
|
| 553 |
+
/**
|
| 554 |
+
* تخصيص السياسة
|
| 555 |
+
* Customize policy
|
| 556 |
+
*/
|
| 557 |
+
customizePolicy(basePolicy, analysis, options) {
|
| 558 |
+
let csp = basePolicy.csp;
|
| 559 |
+
const headers = { ...basePolicy.headers };
|
| 560 |
+
|
| 561 |
+
// إضافة مصادر خارجية للسكريبت
|
| 562 |
+
if (analysis.externalResources.scripts.length > 0) {
|
| 563 |
+
const scriptDomains = analysis.externalResources.scripts
|
| 564 |
+
.map(resource => this.extractDomain(resource.src))
|
| 565 |
+
.filter(domain => domain);
|
| 566 |
+
|
| 567 |
+
if (scriptDomains.length > 0) {
|
| 568 |
+
csp = csp.replace("script-src 'self'",
|
| 569 |
+
`script-src 'self' ${scriptDomains.map(domain => `${domain}`).join(' ')}`);
|
| 570 |
+
}
|
| 571 |
+
}
|
| 572 |
+
|
| 573 |
+
// إضافة مصادر خارجية للأنماط
|
| 574 |
+
if (analysis.externalResources.styles.length > 0) {
|
| 575 |
+
const styleDomains = analysis.externalResources.styles
|
| 576 |
+
.map(resource => this.extractDomain(resource.href))
|
| 577 |
+
.filter(domain => domain);
|
| 578 |
+
|
| 579 |
+
if (styleDomains.length > 0) {
|
| 580 |
+
csp = csp.replace("style-src 'self'",
|
| 581 |
+
`style-src 'self' ${styleDomains.map(domain => `${domain}`).join(' ')}`);
|
| 582 |
+
}
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
// إضافة مصادر للخطوط
|
| 586 |
+
if (analysis.externalResources.fonts.length > 0) {
|
| 587 |
+
const fontDomains = analysis.externalResources.fonts
|
| 588 |
+
.map(resource => this.extractDomain(resource.href))
|
| 589 |
+
.filter(domain => domain);
|
| 590 |
+
|
| 591 |
+
if (fontDomains.length > 0) {
|
| 592 |
+
csp = csp.replace("font-src 'self'",
|
| 593 |
+
`font-src 'self' ${fontDomains.map(domain => `${domain}`).join(' ')}`);
|
| 594 |
+
}
|
| 595 |
+
}
|
| 596 |
+
|
| 597 |
+
// إضافة connect-src للموارد الخارجية
|
| 598 |
+
if (analysis.externalResources.scripts.some(r => r.src.includes('api')) ||
|
| 599 |
+
analysis.externalResources.scripts.some(r => r.src.includes('cdn'))) {
|
| 600 |
+
const apiDomains = [
|
| 601 |
+
...analysis.externalResources.scripts
|
| 602 |
+
.filter(r => r.src.includes('api') || r.src.includes('cdn'))
|
| 603 |
+
.map(r => this.extractDomain(r.src))
|
| 604 |
+
].filter(domain => domain);
|
| 605 |
+
|
| 606 |
+
if (apiDomains.length > 0) {
|
| 607 |
+
csp += ` connect-src 'self' ${apiDomains.map(domain => `${domain}`).join(' ')}`;
|
| 608 |
+
}
|
| 609 |
+
}
|
| 610 |
+
|
| 611 |
+
// معالجة النماذج
|
| 612 |
+
if (analysis.forms.length > 0) {
|
| 613 |
+
const formActions = analysis.forms
|
| 614 |
+
.map(form => this.extractDomain(form.action))
|
| 615 |
+
.filter(domain => domain);
|
| 616 |
+
|
| 617 |
+
if (formActions.length > 0) {
|
| 618 |
+
csp = csp.replace("form-action 'self'",
|
| 619 |
+
`form-action 'self' ${formActions.map(domain => `${domain}`).join(' ')}`);
|
| 620 |
+
}
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
// معالجة الإطارات
|
| 624 |
+
if (analysis.iframes.length > 0) {
|
| 625 |
+
const iframeSrcs = analysis.iframes
|
| 626 |
+
.map(iframe => this.extractDomain(iframe.src))
|
| 627 |
+
.filter(domain => domain);
|
| 628 |
+
|
| 629 |
+
if (iframeSrcs.length > 0) {
|
| 630 |
+
csp = csp.replace("frame-ancestors 'none'",
|
| 631 |
+
`frame-ancestors 'self' ${iframeSrcs.map(domain => `${domain}`).join(' ')}`);
|
| 632 |
+
} else {
|
| 633 |
+
csp = csp.replace("frame-ancestors 'none'", "frame-ancestors 'self'");
|
| 634 |
+
}
|
| 635 |
+
}
|
| 636 |
+
|
| 637 |
+
// تحديث header CSP
|
| 638 |
+
headers['Content-Security-Policy'] = csp;
|
| 639 |
+
|
| 640 |
+
// إضافة nonce للسكريبت المضمنة إذا كانت مطلوبة
|
| 641 |
+
if (analysis.scripts.some(script => script.hasInline) &&
|
| 642 |
+
options.includeNonce !== false) {
|
| 643 |
+
const nonce = this.generateNonce();
|
| 644 |
+
csp = csp.replace("'unsafe-inline'", `'nonce-${nonce}'`);
|
| 645 |
+
headers['Content-Security-Policy'] = csp;
|
| 646 |
+
headers['Content-Security-Policy-Script-Nonce'] = nonce;
|
| 647 |
+
}
|
| 648 |
+
|
| 649 |
+
return {
|
| 650 |
+
name: basePolicy.name,
|
| 651 |
+
description: basePolicy.description,
|
| 652 |
+
csp: csp,
|
| 653 |
+
headers: headers,
|
| 654 |
+
analysis: analysis
|
| 655 |
+
};
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
/**
|
| 659 |
+
* تحسين السياسة
|
| 660 |
+
* Optimize policy
|
| 661 |
+
*/
|
| 662 |
+
optimizePolicy(policy, analysis) {
|
| 663 |
+
const optimized = { ...policy };
|
| 664 |
+
|
| 665 |
+
// إزالة القواعد المكررة
|
| 666 |
+
optimized.csp = this.removeDuplicateDirectives(optimized.csp);
|
| 667 |
+
|
| 668 |
+
// تحسين الأذونات
|
| 669 |
+
if (analysis.javascriptFeatures.includes('ServiceWorker')) {
|
| 670 |
+
optimized.csp += " worker-src 'self'";
|
| 671 |
+
}
|
| 672 |
+
|
| 673 |
+
if (analysis.javascriptFeatures.includes('WebRTC')) {
|
| 674 |
+
optimized.csp += " media-src 'self'";
|
| 675 |
+
}
|
| 676 |
+
|
| 677 |
+
// إضافة SRI للموارد الخارجية
|
| 678 |
+
optimized = this.addSRI(optimized, analysis);
|
| 679 |
+
|
| 680 |
+
return optimized;
|
| 681 |
+
}
|
| 682 |
+
|
| 683 |
+
/**
|
| 684 |
+
* إضافة التوصيات
|
| 685 |
+
* Add recommendations
|
| 686 |
+
*/
|
| 687 |
+
addRecommendations(policy, analysis) {
|
| 688 |
+
const recommendations = [];
|
| 689 |
+
|
| 690 |
+
// توصيات بناءً على التحليل
|
| 691 |
+
if (analysis.securityHeaders['Content-Security-Policy']) {
|
| 692 |
+
recommendations.push({
|
| 693 |
+
type: 'improvement',
|
| 694 |
+
title: 'تحديث CSP الحالي',
|
| 695 |
+
description: 'تم اكتشاف CSP موجود، سيتم تحديثه',
|
| 696 |
+
priority: 'medium'
|
| 697 |
+
});
|
| 698 |
+
}
|
| 699 |
+
|
| 700 |
+
if (analysis.scripts.some(script => script.hasInline && !script.nonce)) {
|
| 701 |
+
recommendations.push({
|
| 702 |
+
type: 'security',
|
| 703 |
+
title: 'إضافة Nonce للسكريبت المضمنة',
|
| 704 |
+
description: 'يجب إضافة nonce أو hash للسكريبت المضمنة لأمان أفضل',
|
| 705 |
+
priority: 'high'
|
| 706 |
+
});
|
| 707 |
+
}
|
| 708 |
+
|
| 709 |
+
if (analysis.forms.length > 0 && !analysis.forms.some(form => form.hasCSRF)) {
|
| 710 |
+
recommendations.push({
|
| 711 |
+
type: 'security',
|
| 712 |
+
title: 'إضافة حماية CSRF',
|
| 713 |
+
description: 'النماذج تحتاج حماية من هجمات CSRF',
|
| 714 |
+
priority: 'high'
|
| 715 |
+
});
|
| 716 |
+
}
|
| 717 |
+
|
| 718 |
+
if (analysis.externalResources.scripts.some(r => !r.integrity)) {
|
| 719 |
+
recommendations.push({
|
| 720 |
+
type: 'security',
|
| 721 |
+
title: 'إضافة Subresource Integrity',
|
| 722 |
+
description: 'يجب إضافة integrity للموارد الخارجية',
|
| 723 |
+
priority: 'medium'
|
| 724 |
+
});
|
| 725 |
+
}
|
| 726 |
+
|
| 727 |
+
return {
|
| 728 |
+
...policy,
|
| 729 |
+
recommendations: recommendations
|
| 730 |
+
};
|
| 731 |
+
}
|
| 732 |
+
|
| 733 |
+
/**
|
| 734 |
+
* توليد توصيات التنفيذ
|
| 735 |
+
* Generate implementation recommendations
|
| 736 |
+
*/
|
| 737 |
+
generateImplementationRecommendations(policy) {
|
| 738 |
+
const recommendations = [];
|
| 739 |
+
|
| 740 |
+
// توصيات HTTP Headers
|
| 741 |
+
recommendations.push({
|
| 742 |
+
category: 'HTTP Headers',
|
| 743 |
+
items: Object.entries(policy.headers).map(([header, value]) => ({
|
| 744 |
+
header,
|
| 745 |
+
value,
|
| 746 |
+
description: this.getHeaderDescription(header)
|
| 747 |
+
}))
|
| 748 |
+
});
|
| 749 |
+
|
| 750 |
+
// توصيات CSP
|
| 751 |
+
recommendations.push({
|
| 752 |
+
category: 'Content Security Policy',
|
| 753 |
+
items: [{
|
| 754 |
+
directive: 'Content-Security-Policy',
|
| 755 |
+
value: policy.csp,
|
| 756 |
+
description: 'سياسة أمان المحتوى الرئيسية'
|
| 757 |
+
}]
|
| 758 |
+
});
|
| 759 |
+
|
| 760 |
+
// توصيات إضافية
|
| 761 |
+
recommendations.push({
|
| 762 |
+
category: 'Additional Security',
|
| 763 |
+
items: [
|
| 764 |
+
{
|
| 765 |
+
header: 'X-Content-Type-Options',
|
| 766 |
+
value: 'nosniff',
|
| 767 |
+
description: 'منع MIME type sniffing'
|
| 768 |
+
},
|
| 769 |
+
{
|
| 770 |
+
header: 'X-Frame-Options',
|
| 771 |
+
value: 'DENY',
|
| 772 |
+
description: 'منع تضمين الموقع في إطارات'
|
| 773 |
+
},
|
| 774 |
+
{
|
| 775 |
+
header: 'X-XSS-Protection',
|
| 776 |
+
value: '1; mode=block',
|
| 777 |
+
description: 'تفعيل حماية XSS في المتصفح'
|
| 778 |
+
}
|
| 779 |
+
]
|
| 780 |
+
});
|
| 781 |
+
|
| 782 |
+
return recommendations;
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
/**
|
| 786 |
+
* توليد دليل التنفيذ
|
| 787 |
+
* Generate implementation guide
|
| 788 |
+
*/
|
| 789 |
+
generateImplementationGuide(policy) {
|
| 790 |
+
return {
|
| 791 |
+
overview: 'دليل تنفيذ سياسة الأمان',
|
| 792 |
+
steps: [
|
| 793 |
+
{
|
| 794 |
+
step: 1,
|
| 795 |
+
title: 'إضافة HTTP Headers',
|
| 796 |
+
description: 'أضف الرؤوس الأمنية التالية إلى خادمك',
|
| 797 |
+
code: this.generateServerConfig(policy.headers),
|
| 798 |
+
platforms: {
|
| 799 |
+
apache: this.generateApacheConfig(policy.headers),
|
| 800 |
+
nginx: this.generateNginxConfig(policy.headers),
|
| 801 |
+
nodejs: this.generateNodeJSConfig(policy.headers),
|
| 802 |
+
php: this.generatePHPConfig(policy.headers)
|
| 803 |
+
}
|
| 804 |
+
},
|
| 805 |
+
{
|
| 806 |
+
step: 2,
|
| 807 |
+
title: 'تحديث Meta Tags',
|
| 808 |
+
description: 'أضف Meta tags للأمان إذا لم تكن متوفرة',
|
| 809 |
+
code: this.generateMetaTags()
|
| 810 |
+
},
|
| 811 |
+
{
|
| 812 |
+
step: 3,
|
| 813 |
+
title: 'اختبار السياسة',
|
| 814 |
+
description: 'اختبر السياسة باستخدام أدوات الاختبار المضمنة',
|
| 815 |
+
action: 'Open CSP Tester'
|
| 816 |
+
},
|
| 817 |
+
{
|
| 818 |
+
step: 4,
|
| 819 |
+
title: 'المراقبة والتحديث',
|
| 820 |
+
description: 'راقب التنبيهات وحديث السياسة حسب الحاجة'
|
| 821 |
+
}
|
| 822 |
+
]
|
| 823 |
+
};
|
| 824 |
+
}
|
| 825 |
+
|
| 826 |
+
/**
|
| 827 |
+
* توليد تكوين الخادم
|
| 828 |
+
* Generate server configuration
|
| 829 |
+
*/
|
| 830 |
+
generateServerConfig(headers) {
|
| 831 |
+
return Object.entries(headers)
|
| 832 |
+
.map(([header, value]) => `Header always set ${header} "${value}"`)
|
| 833 |
+
.join('\n');
|
| 834 |
+
}
|
| 835 |
+
|
| 836 |
+
/**
|
| 837 |
+
* توليد تكوين Apache
|
| 838 |
+
* Generate Apache configuration
|
| 839 |
+
*/
|
| 840 |
+
generateApacheConfig(headers) {
|
| 841 |
+
return `<IfModule mod_headers.c>
|
| 842 |
+
${Object.entries(headers)
|
| 843 |
+
.map(([header, value]) => ` Header always set ${header} "${value}"`)
|
| 844 |
+
.join('\n')}
|
| 845 |
+
</IfModule>`;
|
| 846 |
+
}
|
| 847 |
+
|
| 848 |
+
/**
|
| 849 |
+
* توليد تكوين Nginx
|
| 850 |
+
* Generate Nginx configuration
|
| 851 |
+
*/
|
| 852 |
+
generateNginxConfig(headers) {
|
| 853 |
+
return `location / {
|
| 854 |
+
${Object.entries(headers)
|
| 855 |
+
.map(([header, value]) => ` add_header ${header} "${value}" always;`)
|
| 856 |
+
.join('\n')}
|
| 857 |
+
}`;
|
| 858 |
+
}
|
| 859 |
+
|
| 860 |
+
/**
|
| 861 |
+
* توليد تكوين Node.js
|
| 862 |
+
* Generate Node.js configuration
|
| 863 |
+
*/
|
| 864 |
+
generateNodeJSConfig(headers) {
|
| 865 |
+
return `const express = require('express');
|
| 866 |
+
const app = express();
|
| 867 |
+
|
| 868 |
+
// إضافة الرؤوس الأمنية
|
| 869 |
+
${Object.entries(headers)
|
| 870 |
+
.map(([header, value]) => `app.use((req, res, next) => {
|
| 871 |
+
res.setHeader('${header}', '${value}');
|
| 872 |
+
next();
|
| 873 |
+
});`)
|
| 874 |
+
.join('\n\n')}
|
| 875 |
+
|
| 876 |
+
app.listen(3000);`;
|
| 877 |
+
}
|
| 878 |
+
|
| 879 |
+
/**
|
| 880 |
+
* توليد تكوين PHP
|
| 881 |
+
* Generate PHP configuration
|
| 882 |
+
*/
|
| 883 |
+
generatePHPConfig(headers) {
|
| 884 |
+
return `<?php
|
| 885 |
+
// إضافة الرؤوس الأمنية
|
| 886 |
+
${Object.entries(headers)
|
| 887 |
+
.map(([header, value]) => `header('${header}: ${value}');`)
|
| 888 |
+
.join('\n')}
|
| 889 |
+
|
| 890 |
+
// أو في .htaccess
|
| 891 |
+
/*
|
| 892 |
+
|
| 893 |
+
${this.generateApacheConfig(headers)}
|
| 894 |
+
|
| 895 |
+
*/`;
|
| 896 |
+
}
|
| 897 |
+
|
| 898 |
+
/**
|
| 899 |
+
* توليد Meta Tags
|
| 900 |
+
* Generate Meta tags
|
| 901 |
+
*/
|
| 902 |
+
generateMetaTags() {
|
| 903 |
+
return `<meta charset="UTF-8">
|
| 904 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 905 |
+
<meta name="description" content="وصف الموقع">
|
| 906 |
+
<meta name="robots" content="index, follow">`;
|
| 907 |
+
}
|
| 908 |
+
|
| 909 |
+
/**
|
| 910 |
+
* استخراج النطاق
|
| 911 |
+
* Extract domain
|
| 912 |
+
*/
|
| 913 |
+
extractDomain(url) {
|
| 914 |
+
try {
|
| 915 |
+
const urlObj = new URL(url);
|
| 916 |
+
return urlObj.hostname;
|
| 917 |
+
} catch {
|
| 918 |
+
return null;
|
| 919 |
+
}
|
| 920 |
+
}
|
| 921 |
+
|
| 922 |
+
/**
|
| 923 |
+
* إزالة التوجيهات المكررة
|
| 924 |
+
* Remove duplicate directives
|
| 925 |
+
*/
|
| 926 |
+
removeDuplicateDirectives(csp) {
|
| 927 |
+
const directives = {};
|
| 928 |
+
const parts = csp.split(';').map(part => part.trim()).filter(part => part);
|
| 929 |
+
|
| 930 |
+
parts.forEach(part => {
|
| 931 |
+
const [directive, ...values] = part.split(' ');
|
| 932 |
+
if (directive && !directives[directive]) {
|
| 933 |
+
directives[directive] = values.join(' ');
|
| 934 |
+
}
|
| 935 |
+
});
|
| 936 |
+
|
| 937 |
+
return Object.entries(directives)
|
| 938 |
+
.map(([directive, values]) => `${directive} ${values}`)
|
| 939 |
+
.join('; ');
|
| 940 |
+
}
|
| 941 |
+
|
| 942 |
+
/**
|
| 943 |
+
* إضافة SRI
|
| 944 |
+
* Add SRI
|
| 945 |
+
*/
|
| 946 |
+
addSRI(policy, analysis) {
|
| 947 |
+
// في التطبيق الحقيقي، ستحسب hashes للموارد
|
| 948 |
+
// هنا نضيف فقط توصية
|
| 949 |
+
if (analysis.externalResources.scripts.some(r => !r.integrity)) {
|
| 950 |
+
policy.recommendations.push({
|
| 951 |
+
type: 'security',
|
| 952 |
+
title: 'إضافة Subresource Integrity',
|
| 953 |
+
description: 'أضف integrity="sha256-..." للسكريبت الخارجية',
|
| 954 |
+
priority: 'medium'
|
| 955 |
+
});
|
| 956 |
+
}
|
| 957 |
+
|
| 958 |
+
return policy;
|
| 959 |
+
}
|
| 960 |
+
|
| 961 |
+
/**
|
| 962 |
+
* توليد Nonce
|
| 963 |
+
* Generate nonce
|
| 964 |
+
*/
|
| 965 |
+
generateNonce() {
|
| 966 |
+
const array = new Uint8Array(16);
|
| 967 |
+
crypto.getRandomValues(array);
|
| 968 |
+
return btoa(String.fromCharCode(...array));
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
/**
|
| 972 |
+
* الحصول على وصف Header
|
| 973 |
+
* Get header description
|
| 974 |
+
*/
|
| 975 |
+
getHeaderDescription(header) {
|
| 976 |
+
const descriptions = {
|
| 977 |
+
'Content-Security-Policy': 'سياسة أمان المحتوى',
|
| 978 |
+
'X-Content-Type-Options': 'منع MIME type sniffing',
|
| 979 |
+
'X-Frame-Options': 'منع clickjacking',
|
| 980 |
+
'X-XSS-Protection': 'حماية XSS',
|
| 981 |
+
'Strict-Transport-Security': 'فرض HTTPS',
|
| 982 |
+
'Referrer-Policy': 'سياسة المرجع',
|
| 983 |
+
'Permissions-Policy': 'سياسة الأذونات',
|
| 984 |
+
'Cross-Origin-Opener-Policy': 'عزل المصادر المتقاطعة',
|
| 985 |
+
'Cross-Origin-Embedder-Policy': 'سياسة تضمين المصادر المتقاطعة'
|
| 986 |
+
};
|
| 987 |
+
return descriptions[header] || 'رأس أمني';
|
| 988 |
+
}
|
| 989 |
+
|
| 990 |
+
/**
|
| 991 |
+
* حفظ تفضيلات المستخدم
|
| 992 |
+
* Save user preferences
|
| 993 |
+
*/
|
| 994 |
+
saveUserPreferences(preferences) {
|
| 995 |
+
this.userPreferences = { ...this.userPreferences, ...preferences };
|
| 996 |
+
localStorage.setItem('smartPolicyUserPreferences', JSON.stringify(this.userPreferences));
|
| 997 |
+
}
|
| 998 |
+
|
| 999 |
+
/**
|
| 1000 |
+
* تحميل تفضيلات المستخدم
|
| 1001 |
+
* Load user preferences
|
| 1002 |
+
*/
|
| 1003 |
+
loadUserPreferences() {
|
| 1004 |
+
try {
|
| 1005 |
+
const saved = localStorage.getItem('smartPolicyUserPreferences');
|
| 1006 |
+
return saved ? JSON.parse(saved) : {};
|
| 1007 |
+
} catch {
|
| 1008 |
+
return {};
|
| 1009 |
+
}
|
| 1010 |
+
}
|
| 1011 |
+
|
| 1012 |
+
/**
|
| 1013 |
+
* حفظ بيانات التعلم
|
| 1014 |
+
* Save learning data
|
| 1015 |
+
*/
|
| 1016 |
+
saveLearningData(data) {
|
| 1017 |
+
this.learningData = { ...this.learningData, ...data };
|
| 1018 |
+
localStorage.setItem('smartPolicyLearningData', JSON.stringify(this.learningData));
|
| 1019 |
+
}
|
| 1020 |
+
|
| 1021 |
+
/**
|
| 1022 |
+
* تحميل بيانات التعلم
|
| 1023 |
+
* Load learning data
|
| 1024 |
+
*/
|
| 1025 |
+
loadLearningData() {
|
| 1026 |
+
try {
|
| 1027 |
+
const saved = localStorage.getItem('smartPolicyLearningData');
|
| 1028 |
+
return saved ? JSON.parse(saved) : { generated: [], feedback: [] };
|
| 1029 |
+
} catch {
|
| 1030 |
+
return { generated: [], feedback: [] };
|
| 1031 |
+
}
|
| 1032 |
+
}
|
| 1033 |
+
}
|
| 1034 |
+
|
| 1035 |
+
// تصدير الكلاس للاستخدام
|
| 1036 |
+
window.SmartPolicyGenerator = SmartPolicyGenerator;
|