لدي بعض المستخدمين الهندسيين الذين يرغبون في إرفاق بعض ملفات البيانات بامتدادات ملفات غير شائعة بمنشوراتهم. إنها في الأساس ملفات نصية عادية ولكنها تتضمن أحرف ASCII الموسعة.
لقد حاولت تحديث تكوين NGINX الخاص بـ Discourse لتحديد أنواع وسائط MIME لهذه الملفات ولكنه لم ينجح. لقد نشرت موضوعًا (How to customize MIME media type emitted for certain attachments?) حول هذا الأمر قبل أسبوعين ولكن لم أتلق أي إجابات حتى الآن. حتى لو لم يتم تحديث NGINX، فسيظل يقدم أنواع الملفات غير المعروفة باستخدام نوع MIME الافتراضي “application/octet-stream”. يمكنني التعايش مع ذلك في الوقت الحالي.
ومع ذلك، عندما يحاول المستخدمون تحميل ملفات البيانات هذه في منشور (إما باستخدام زر “تحميل” أو السحب والإفلات)، فإنهم يحصلون على نافذة منبثقة للخطأ من Discourse مثل هذه:
يبدو أنه عندما يقوم المستخدمون بتحميل الملفات، يحاول Discourse أن يكون ذكيًا ويكتشف ما إذا كان صورة أو نوع ملف آخر. علاوة على ذلك، يبدو أنه يقوم بهذا التحديد من خلال النظر إلى محتويات الملف (على غرار الأمر القياسي في Unix “file”). أفترض أن هذا حتى يقرر Discourse ما إذا كان سيضمنه في محتوى المنشور أو يضعه جانبًا كمرفق.
في حالة ملفات البيانات هذه، فإن هذا الفحص يحدد الملفات بشكل غير صحيح على أنها صور. فقط للمرح، وضعت بعضًا من ملفات البيانات هذه على جهاز Ubuntu وتحققت منها باستخدام الأمر “file”، وبالتأكيد، تم تحديدها على أنها “بيانات صور JPEG”.
هل هناك طريقة للمستخدمين لتحميل الملفات دون محاولة Discourse اكتشاف ما إذا كانت صورًا؟ أي، “يرجى تحميل هذا كمرفق، بغض النظر عن ماهيته، لا تضمنه”؟
بدلاً من ذلك، يمكنني تكوين Discourse للسماح بملفات zip وإخبار المستخدمين بضغط ملفاتهم قبل تحميلها، لكنني أفضل عدم فتح الموقع لتحميلات ملفات zip عشوائية. يبدو هذا مشكلة أمنية.
هناك حل آخر يتمثل في اعتماد امتداد لتلك الملفات الغريبة، مثل .bin أو .data أو حتى .anythinggoes، والتي يجب أن تكون كافية لـ Discourse لترك هذه الملفات وشأنها.
باختصار، يتم اكتشاف ملفك على أنه JPEG لأنه يبدأ بنفس التوقيع الخاص بهذا النوع من الملفات.
إصلاح هذا السلوك في Discourse ممكن، ولكنه يتطلب تعديلاً. (انظر في النهاية)
إليك بعض الأمور التقنية.
تبدأ هذه المشكلة هنا:
مكتبة FastImage تفتح الملف وتحدد النوع والحجم.
كما تتوقع، فإنها تُرجع نوع JPEG.
الآن، إذا نظرت إلى كيفية اكتشاف FastImage لملف JPEG، يمكنك رؤية ذلك هنا:
ومع ذلك، لا يمكنك استخراج أي معلومات عن الصورة نظرًا لعدم وجود جميع البايتات المطلوبة.
كيف نحل هذه المشكلة في Discourse؟
بالنظر إلى كود FastImage، هناك خيار قيم يمكنك تمريره.
باستخدام هذا الخيار، أي خطأ (SizeNotFound، ImageFetchFailure، CannotParseImage، UnknownImageType، BadImageURI) لن يُرجع أي معلومات عن الصورة؛ ولن يتم اكتشاف ملفك كصورة.
@image_info =
begin
FastImage.new(@file, :raise_on_failure => true)
rescue StandardError
nil
end
...
is_image ||= @image_info && FileHelper.is_supported_image?("test.#{@image_info.type}")
مع هذه التغييرات، لن يتم اكتشاف الملف كصورة وسيتم تحميله كغير صورة وعرضه على يمين المنشور؟
إذا فهمت بشكل صحيح، فإنك تقترح علي إجراء هذه التعديلات في نسختي المحلية من Discourse لتجربتها و/أو استخدامها حتى يتم تضمينها في إصدار مستقبلي من Discourse. ولكن كيف أفعل ذلك؟ (أنا مطور برامج ذو خبرة ولكن لدي خبرة محدودة في Docker ولا خبرة لدي في Ruby.)
استدعاء FastImage الذي سيحتاج إلى تعديل موجود في models/upload.rb، أليس كذلك؟
نعم، هذا صحيح – كما في لقطة الشاشة الخاصة بي أعلاه
أنا لا أقترح عليك إجراء التعديل. ومع ذلك، إذا لم تتمكن من الانتظار، يمكنك بالتأكيد اختبار هذا التغيير.
لتغيير مؤقت (يختفي بعد إعادة البناء):
cd /var/discourse
./launcher enter app
sed -i "s/FastImage.new(@file)/FastImage.new(@file, :raise_on_failure=true)/" lib/upload_creator.rb
sed -i "s/FastImage.new(original_path)/FastImage.new(original_path, :raise_on_failure=true)/" app/models/upload.rb
exit
لتغيير دائم (يبقى بعد إعادة البناء):
cd /var/discourse
nano containers/app.yml (استخدم محرر النصوص المفضل لديك)
أضف الأوامر المخصصة التالية في النهاية (قسم run):
- replace:
filename: "/var/www/discourse/lib/upload_creator.rb"
from: "FastImage.new(@file)"
to: "FastImage.new(@file, :raise_on_failure=true)"
- replace:
filename: "/var/www/discourse/app/models/upload.rb"
from: "FastImage.new(original_path)"
to: "FastImage.new(original_path, :raise_on_failure=true)"
ثم، أعد البناء:
./launcher rebuild app
أعتقد ذلك إذا كنت تخطط لتحميل ملفات بدون امتدادات. لم أتحقق مما إذا كانت هناك حالات أخرى تتطلب نفس التغيير.