STACKDUST
EN
مخطط يقارن ثلاثة أجزاء من BentoPDF: المتصفح حيث يجري تحرير النص وإعادة التدفق ومطابقة الخطوط والدمج والتقسيم وOCR والضغط، ولا يغادره الملف نفسه؛ والحاوية وهي nginx غير مُمتاز يقدّم ملفات ثابتة على المنفذ 8080 بلا خادم تطبيق وبلا نقطة رفع؛ والاستثناء وهو وسيط CORS اختياري لاستعلامات الشهادات والطوابع الزمنية تقع فيه اثنتان من ثلاث نشرات أمنية صدرت في أغسطس. وأسفله جدول بأربع نشرات أمنية منشورة بدرجات خطورتها والإصدارات التي عالجتها

BentoPDF صار يحرّر نص الـPDF داخل المتصفح — وحاويته مجرد nginx


كل بضعة أشهر تحتاج إلى عمل شيء غير مثير على ملف PDF — دمج ملفين، حذف صفحة، ضغطه ليمرّ من حدّ الرفع، توقيعه. وكل بضعة أشهر تلصقه في أول موقع يظهر لك في نتائج البحث عن «دمج PDF»، أي أنك تسلّم مستنداً لم تقرأه بما يكفي إلى خادم لا تعرف عنه شيئاً.

BentoPDF هو الجواب على ذلك، وفي ٢٩ أغسطس ٢٠٢٦ صدر منه الإصدار 2.8.8 الذي يضيف تحرير النص الفعلي داخل ملف الـPDF. هذا سبب الكتابة عنه اليوم. أما سبب استحقاقه للاستضافة الذاتية فأقدم وأعمق بنيةً، ويمكنك التحقق منه في دقيقة واحدة بقراءة ملف Dockerfile.

ما هو

حقيبة أدوات PDF تعمل داخل المتصفح. دمج وتقسيم وتدوير وضغط وتعرّف ضوئي على الحروف (OCR) وتحويل وتوقيع وحجب — المصفوفة المعتادة — يضاف إليها في هذا الإصدار تحرير النص في مكانه.

يصف المشروع نفسه بأنه «حقيبة أدوات PDF تضع الخصوصية أولاً»، وملف الـREADME صريح في الآلية: «كل المعالجة تجري في متصفحك. ملفاتك لا تُرفع أبداً إلى خادم، بما يضمن خصوصية بنسبة ١٠٠٪». عبارة تسويقية كهذه هي عادةً موضع الشك في أي مقال. غير أن هذا الادعاء بالذات قابل للفحص — وقد صمد. التفصيل في القسم التالي.

الأرقام: ١٤٬٩٣٢ نجمة، أول commit في أكتوبر ٢٠٢٥، وآخر دفعة شيفرة في ٢٩ أغسطس ٢٠٢٦. الترخيص AGPL-3.0 بملف LICENSE حقيقي لا شارة في الواجهة. ويصونه فرد لا شركة — يسجّل GitHub المالك بوصفه حساباً شخصياً، وملاحظات الإصدار تُقرأ كسجل تغييرات شخص واحد، ومنها عبارته: «هذه أصعب ميزة بنيتها حتى الآن على الأرجح».

لماذا لم تسمع به

لأن Stirling-PDF موجود ويحمل ٩٠٬٩٠٥ نجمة. هو يحتل خانة «أدوات PDF مستضافة ذاتياً» في أذهان الجميع منذ ٢٠٢٣، وهو ما توصي به كل نقاشات المختبرات المنزلية، وهو جيد فعلاً. وحين يكون في الفئة لاعب مترسّخ بهذا الحجم، يصير مشروع عمره عشرة أشهر بسدس عدد نجومه غير مرئي مهما بلغت جدارته.

والسبب الثاني أن BentoPDF لا يبدو بنية تحتية. له موقع عام يعمل بلا تسجيل، فأغلب من يصادفه يستخدم النسخة المستضافة ولا ينتبه أصلاً إلى وجود حاوية.

كيف يعمل

هنا الجزء الذي يمكنك التحقق منه بنفسك. ملف Dockerfile بناء من مرحلتين: مرحلة بناء على node:20-alpine تنتج مجلد dist/، ثم مرحلة تشغيل على nginx-unprivileged:alpine-slim بتعليمة واحدة ذات معنى:

COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html${BASE_URL%/}

هذا هو الخادم كله. لا زمن تشغيل تطبيقي في الصورة النهائية، ولا طابور، ولا عامل خلفي، ولا معالج رفع — مجرد nginx يقدّم أصولاً ثابتة على المنفذ 8080. وعمل الـPDF يجري في WebAssembly داخل متصفح الزائر، ولهذا فادعاء الخصوصية بنيوي لا وعد: خادم لا يملك نقطة نهاية تستقبل ملفاً لا يستطيع استقبال ملفك، مهما قالت سياسة الخصوصية.

وهذا نقيض تصميم Stirling-PDF الذي ينجز العمل على الخادم بلغة Java. وليس أحدهما خطأً. المعالجة على الخادم تمنحك نتائج متسقة لا تتعلق بجهاز العميل، وتتعامل مع ملفات أكبر من طاقة لسان المتصفح؛ والمعالجة في العميل تعني أن المستند لا يتحرك أصلاً. نموذجا ثقة مختلفان، ويجدر بك أن تعرف أيّهما نشرت.

وتحرير النص في 2.8.8 هو البرهان المثير على هذا النموذج. تنقر فقرة وتكتب؛ يعيد النص تدفقه حيّاً، وتُطابَق الخطوط، ويدعم العريض والمائل والمحاذاة والقوائم والبحث والاستبدال والتدقيق الإملائي بقاموس شخصي، والنص من اليمين إلى اليسار ومن اليسار إلى اليمين. كل ذلك داخل اللسان. وقيد واحد موثّق: الوصول إلى الخطوط المحلية يعمل فقط على متصفحات Chromium، لأن واجهة Local Font Access غير متاحة في غيرها.

ويضيف الإصدار محرّكَي ضغط: Kura وHyper Compress. ويذكر المشروع أنه قاس Hyper مقابل Ghostscript وMuPDF وqpdf على ٢٬١٠٤ ملف PDF واقعي و٢٧٬٣٥٢ تشغيلة محرّك، مدّعياً معدل إفساد ٠٫٣٩٪ — «الأدنى بين كل المحركات المقيسة» — وضماناً بألّا يعيد ملفاً أكبر من الأصل أبداً. وتعامل مع هذه الأرقام بما هي عليه: قياس المشروع لمحرّكه هو نفسه، منشور في ملاحظات إصداره، ولم يُعِد أحد إنتاجه بشكل مستقل. المنهجية موصوفة والمحرّك مفتوح المصدر، فالادعاء قابل للتفنيد — لكن للمستودع ست نجوم وقد دُفع إليه أمس، فلم يفنّده أحد بعد ولم يؤكده.

تشغيله

ملف compose في المستودع أربعة أسطر ذات مضمون:

services:
  bentopdf:
    image: ghcr.io/alam00000/bentopdf-simple:latest
    container_name: bentopdf
    restart: unless-stopped
    ports:
      - '8080:8080'

انتبه لاسم الصورة. المستودع ينشر صورتين، وتعليقات ملف compose نفسها تشرح الفرق:

Self-Hosted build - ghcr.io/alam00000/bentopdf-simple:latest
Commercial build  - ghcr.io/alam00000/bentopdf:latest

وbentopdf-simple هي المطلوبة. وبوصف المشروع تضم «كل أداة PDF في الموقع العام، بلا تسويق BentoPDF (بلا واجهة ترويجية ولا أسئلة شائعة ولا شهادات ولا تذييل)» — الأدوات متطابقة، والمحذوف هو صفحة الهبوط. وهذا فصل صريح ومنعش، ويستحق المقارنة بـخط الترخيص الذي وجدناه في بوابة Pangolin قبل أيام، حيث كانت وحدة التحليلات في النسخة المفتوحة غلافاً بدوال فارغة. أما هنا فنسخة الاستضافة الذاتية كاملة وظيفياً.

ويوجد ترخيص تجاري — بسعر معلن ٧٩ دولاراً دفعة واحدة — لكنه يشتري إعفاءً من التزامات AGPL لمن يدمج BentoPDF في منتجات مغلقة. وهو لا يحجب ميزات عن المستضيفين ذاتياً.

ولأنه بلا خادم تطبيق فهو كذلك بلا قاعدة بيانات وبلا ملف بيئة وبلا شيء تحتاج إلى نسخه احتياطياً. ضعه خلف الوسيط العكسي الذي تشغّله أصلاً وانتهى الأمر.

ما الذي يستبدله

مباشرةً: مواقع الـPDF المجانية. هذا هو العرض الصادق، وهو عرض جيد.

أما مقابل Stirling-PDF فالمقارنة بنيوية لا ميزة بميزة. لدى Stirling-PDF مساحة أدوات أوسع، ومجتمع أكبر بكثير، ومعالجة على الخادم لا تكترث بعمر جهاز العميل. ولدى BentoPDF نموذج الثقة — وأثر تشغيلي أصغر بكثير، إذ إن حاوية ملفات ثابتة أقرب إلى انعدام الصيانة من خدمة تعمل على JVM.

وإن كنت تتعامل مع مستندات حساسة فعلاً — عقود، سجلات طبية، أي شيء يكون فيه سؤال «هل عُولج على خادم؟» سؤالاً مُلزماً — فالنموذج العامل في المتصفح هو ما يتيح لك جواباً نظيفاً.

القيود

السجل الأمني يستحق فقرة كاملة لا هامشاً. في المستودع أربع نشرات أمنية منشورة، وإن كنت تثبّت وسم صورة فعليك معرفتها:

النشرة الخطورة المشكلة عولجت في
CVE-2026-41653 عالية XSS مخزّن في أداة Markdown إلى PDF v2.8.3
CVE-2026-77581 متوسطة SSRF بتجاوز قائمة السماح في وسيط CORS v2.8.7
GHSA-wh78-rcw2-hhg9 متوسطة SSRF عبر إعادة ربط DNS في الوسيط نفسه v2.8.7
CVE-2026-63630 منخفضة استيراد سير عمل يثق برابط TSA من المهاجم v2.8.7

ملاحظتان على هذا الجدول. الأولى أن ثلاثاً من الأربع نُشرت في ٢٣ أغسطس ٢٠٢٦، والمدى المتأثر مذكور بوصفه bentopdf and bentopdf-simple <= 2.8.6 — أي أن نشراً مستضافاً ذاتياً مثبَّتاً على وسم أقدم داخل النطاق، لا الموقع العام وحده. وحُسن تعامل المشروع مع ذلك يُحسب له: نسب الاكتشاف إلى مبلّغيه بأسمائهم، وأصدر v2.8.7 بوصفه إصداراً أمنياً صريحاً.

والثانية أعمّ فائدة: حتى لحظة الكتابة تُحَلّ هذه النشرات على مستوى المستودع لكنها ليست في قاعدة النشرات العامة لدى GitHub — الاستعلام عنها هناك يرجع 404. وهذا متسق مع نافذة إفصاح منسّق ما زالت مفتوحة، لكنه يعني أن ماسحات الاعتماديات الآلية لن تعرضها لك بالضرورة. راقب صفحة الإصدارات بدل الاتكال على ماسح.

وأطرف ما في الجدول — لأداة قائمة على ادعاء خصوصية — هي النشرة منخفضة الخطورة. استيراد ملف سير عمل مُعَدّ خصيصاً قد يدفع التطبيق إلى إرسال طلب طابع زمني وفق RFC 3161 يحتوي على بصمة SHA-256 لملف الـPDF عندك إلى خادم يختاره المهاجم. ليس المستند، بل بصمته — وهي كافية لتأكيد امتلاكك ملفاً بعينه لطرف ثالث. إنها ثلمة صغيرة ودقيقة في عبارة «لا شيء يغادر متصفحك»، وهي تحديداً شكل الثغرات التي ستظل هذه البنية تنتجها: النواة مغلقة، فتهاجر المخاطرة إلى الميزات القليلة المضطرة لمخاطبة الشبكة. ولهذا السبب نفسه يستأثر وسيط CORS الاختياري — المستخدَم لاستعلامات الشهادات والطوابع الزمنية — باثنتين من نشرات أغسطس الثلاث.

وقيدان أخف. هذا مشروع مطوّر واحد؛ و«عامل الحافلة» المساوي واحداً اعتبار حقيقي لشيء تنشره لفريق. والمعالجة في المتصفح لها سقف — ملف PDF ممسوح ضوئياً بحجم مئات الميغابايتات تجربة مختلفة تماماً داخل لسان متصفح عنها داخل JVM.

لمن هو

لكل من يلصق ملفات PDF في المواقع اليوم. انشر bentopdf-simple، وضعه في المفضلة، وتوقّف عن ذلك.

وللفرق الصغيرة التي تتعامل مع مستندات عملاء أو مرضى، حيث يكون النموذج العامل في المتصفح هو الفرق بين نقاش امتثال طويل وجواب قصير. ثبّت وسماً، وراقب صفحة الإصدارات، وكن على v2.8.7 أو أحدث.

وليس لك إن كنت تحتاج خط معالجة واسعاً على الخادم، أو أتمتة دفعية على ملفات ضخمة، أو طمأنينة فريق صيانة كبير. يبقى Stirling-PDF الجواب الأفضل هناك.

الخلاصة

الميزة الرئيسية حقيقية — تحرير نص PDF داخل لسان متصفح مع إعادة تدفق حيّة ومطابقة خطوط عمل صعب فعلاً، والمطوّر نفسه يقول ذلك. لكن سبب تشغيله بدل مجرد استخدامه يقع في ملف Dockerfile: ما تنشره هو nginx ومجلد ملفات ثابتة، وخادم لا يستطيع استقبال رفع لا يستطيع تسريبه.

هذا الضمان بنيوي، وهو ما يجعله أثمن من سياسة خصوصية. وهو كذلك ليس مطلقاً — اقرأ النشرات الأربع، ولاحظ أن اثنتين منها تقعان في المكوّن الاختياري الوحيد الذي يجري اتصالات خارجية، وشغّل v2.8.7 أو أحدث. فالسطح الأمني المثير في تطبيق يعمل داخل المتصفح هو دائماً ذلك الجزء الصغير الذي لا يعمل داخله.

المصادر


المقال التاليمعيار العتاد للنماذج (MHS): كيف تنقل Anthropic وكلاء الذكاء الاصطناعي من شاشات البرمجيات إلى المختبرات الفيزيائيةالمقال السابقبانغولين صار بوابة ذكاء اصطناعي بهدوء — وخطّ الترخيص مكشوف في الشيفرة