Update app.py
Browse files
app.py
CHANGED
|
@@ -155,11 +155,31 @@ def enter_folder(selected_folder, current_rel):
|
|
| 155 |
new_rel = os.path.join(current_rel, selected_folder).strip("/")
|
| 156 |
return new_rel, *scan_directory(new_rel)
|
| 157 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
def load_file_content(selected_file, current_rel):
|
| 159 |
"""
|
| 160 |
يقرأ محتوى الملف المحدد ويعرضه في المحرر.
|
| 161 |
-
تم إصلاح المشكلة: ال
|
| 162 |
-
|
| 163 |
"""
|
| 164 |
if not selected_file or selected_file == "لا توجد ملفات في هذا المسار":
|
| 165 |
return gr.update(value="الرجاء تحديد ملف متاح للقراءة.")
|
|
@@ -167,13 +187,38 @@ def load_file_content(selected_file, current_rel):
|
|
| 167 |
file_path = os.path.join(get_safe_path(current_rel), selected_file)
|
| 168 |
|
| 169 |
if not os.path.isfile(file_path):
|
| 170 |
-
return gr.update(value=f"⚠️ لا يمكن فتح [{selected_file}] لأنه
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 171 |
|
| 172 |
try:
|
| 173 |
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|
| 174 |
content = f.read()
|
| 175 |
-
# نحدد نوع اللغة للتلوين بناءً على الامتداد (اختياري لكن يحسن التجربة)
|
| 176 |
-
ext = os.path.splitext(selected_file)[1].lower()
|
| 177 |
lang_map = {".yml": "yaml", ".yaml": "yaml", ".json": "json",
|
| 178 |
".properties": "yaml", ".txt": None, ".log": None}
|
| 179 |
return gr.update(value=content, language=lang_map.get(ext, None))
|
|
|
|
| 155 |
new_rel = os.path.join(current_rel, selected_folder).strip("/")
|
| 156 |
return new_rel, *scan_directory(new_rel)
|
| 157 |
|
| 158 |
+
|
| 159 |
+
# امتدادات ثنائية معروفة يمنع فتحها كنص إطلاقاً (تتسبب بتجمد الصفحة)
|
| 160 |
+
BINARY_EXTENSIONS = {
|
| 161 |
+
".jar", ".zip", ".gz", ".tar", ".rar", ".7z", ".class",
|
| 162 |
+
".dat", ".mca", ".mcr", ".png", ".jpg", ".jpeg", ".gif",
|
| 163 |
+
".ico", ".exe", ".bin", ".db", ".so", ".dll"
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
# الحد الأقصى لحجم الملف المسموح بفتحه في المحرر (بالبايت) - 1 ميجابايت
|
| 167 |
+
MAX_EDITABLE_SIZE = 1 * 1024 * 1024
|
| 168 |
+
|
| 169 |
+
def is_probably_binary(file_path, chunk_size=1024):
|
| 170 |
+
"""يفحص أول جزء من الملف بحثاً عن بايتات null تدل على أنه ملف ثنائي."""
|
| 171 |
+
try:
|
| 172 |
+
with open(file_path, "rb") as f:
|
| 173 |
+
chunk = f.read(chunk_size)
|
| 174 |
+
return b"\x00" in chunk
|
| 175 |
+
except Exception:
|
| 176 |
+
return True
|
| 177 |
+
|
| 178 |
def load_file_content(selected_file, current_rel):
|
| 179 |
"""
|
| 180 |
يقرأ محتوى الملف المحدد ويعرضه في المحرر.
|
| 181 |
+
تم إصلاح المشكلة: الآن يتم فحص نوع الملف وحجمه قبل القراءة
|
| 182 |
+
لمنع تجمد الصفحة عند فتح ملفات ثنائية (jar, mca, png...) أو ملفات كبيرة جداً.
|
| 183 |
"""
|
| 184 |
if not selected_file or selected_file == "لا توجد ملفات في هذا المسار":
|
| 185 |
return gr.update(value="الرجاء تحديد ملف متاح للقراءة.")
|
|
|
|
| 187 |
file_path = os.path.join(get_safe_path(current_rel), selected_file)
|
| 188 |
|
| 189 |
if not os.path.isfile(file_path):
|
| 190 |
+
return gr.update(value=f"⚠️ لا يمكن فتح [{selected_file}] لأنه مجلد وليس ملفاً.")
|
| 191 |
+
|
| 192 |
+
ext = os.path.splitext(selected_file)[1].lower()
|
| 193 |
+
|
| 194 |
+
# 1) تحقق من الامتداد الثنائي المعروف
|
| 195 |
+
if ext in BINARY_EXTENSIONS:
|
| 196 |
+
return gr.update(
|
| 197 |
+
value=f"🚫 لا يمكن عرض [{selected_file}] في المحرر لأنه ملف ثنائي (Binary) وليس ملف نصي.\n"
|
| 198 |
+
f"هذا النوع من الملفات (jar/zip/png/mca...) لا يُعدّل كنص، بل يُرفع أو يُستبدل فقط عبر خانة الرفع."
|
| 199 |
+
)
|
| 200 |
+
|
| 201 |
+
# 2) تحقق من الحجم لتجنب تجميد المتصفح
|
| 202 |
+
try:
|
| 203 |
+
size = os.path.getsize(file_path)
|
| 204 |
+
except Exception as e:
|
| 205 |
+
return gr.update(value=f"خطأ أثناء قراءة حجم الملف: {e}")
|
| 206 |
+
|
| 207 |
+
if size > MAX_EDITABLE_SIZE:
|
| 208 |
+
return gr.update(
|
| 209 |
+
value=f"🚫 الملف [{selected_file}] حجمه كبير جداً ({size/1024/1024:.2f} MB) وفتحه سيجمّد الصفحة.\n"
|
| 210 |
+
f"الحد المسموح للتحرير هو 1 ميجابايت. استخدم زر الرفع لتبديله بدلاً من فتحه هنا."
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
# 3) فحص إضافي: بايتات null تدل على محتوى ثنائي حتى لو الامتداد نصي
|
| 214 |
+
if is_probably_binary(file_path):
|
| 215 |
+
return gr.update(
|
| 216 |
+
value=f"🚫 الملف [{selected_file}] يحتوي على بيانات ثنائية غير قابلة للعرض كنص."
|
| 217 |
+
)
|
| 218 |
|
| 219 |
try:
|
| 220 |
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|
| 221 |
content = f.read()
|
|
|
|
|
|
|
| 222 |
lang_map = {".yml": "yaml", ".yaml": "yaml", ".json": "json",
|
| 223 |
".properties": "yaml", ".txt": None, ".log": None}
|
| 224 |
return gr.update(value=content, language=lang_map.get(ext, None))
|