در دنیای رایانه شوخی قدیمیای رایج است: DOOM سرانجام روی همهچیز اجرا خواهد شد. نه بهعنوان تعریف از بازی، بلکه بهعنوان یک چالش. این بازی تیراندازی ساخت ۱۹۹۳ را تاکنون روی دستگاههای خودپرداز، چاپگرها، تستهای بارداری، ماشینحسابها، یک قطعهی تنهای LEGO و نوار لمسی مکبوک به کار انداختهاند.
در ژانویهی ۲۰۲۵ یک دانشآموز دبیرستانی مورد تازهای به این فهرست افزود. او DOOM را درون یک فایل PDF اجرا کرد.

خلاصه
یک دانشآموز دبیرستانی DOOM را با نسخهای از Emscripten متعلق به سال ۲۰۲۰ به asm.js ترجمه کرد و آن را درون یک PDF اجرا کرد؛ برای هر سطر صفحه یک فیلد فرم بهجای نمایشگر: ۳۲۰×۲۰۰، شش سایهی خاکستری، حدود ۸۰ میلیثانیه برای هر فریم. هیچ آسیبپذیریای در کار نبود. هر قابلیتی که به کار رفته بخشی مستند از مشخصات PDF است و دقیقاً همان کاری را میکند که برایش طراحی شده. نکتهی جالب همین است — و همین دلیلی است که یکبار ده دقیقه به سندهایتان توجه کنید.
این کاری درخشان و شوخی بسیار خوبی است. همچنین روشنترین گواه بر چیزی است که این سایت مدام تکرار میکند و مردم بهحق باور کردنش را دشوار مییابند: PDF عکسِ یک صفحه نیست. ظرفی است که میتواند کد اجرا کند.
واقعاً چگونه کار میکند
نام پروژه doompdf است، ساختهی توسعهدهندهای که خود را ading2210 مینامد. سازوکارش از خودِ نمایش جالبتر است و چهار بخش دارد.
PDF از JavaScript پشتیبانی میکند. نه بهصورت افزونه یا پلاگین — بخشی از خودِ قالب است، با کتابخانهی استاندارد خودش، و مرورگرها آن را در موتورهای PDF داخلیشان پیاده میکنند. برای این هست که فرمها بتوانند آنچه را تایپ میکنید بررسی کنند و سندهای تعاملی به کلیک پاسخ دهند. هیچکس آن را با فکرِ بازی اضافه نکرد.
کد منبع DOOM عمومی است — هرچند ماجرا دقیقتر از آن چیزی است که خلاصهاش مینمایاند. id Software کد را در ۲۳ دسامبر ۱۹۹۷ منتشر کرد، اما با مجوزی که تنها استفادهی آموزشی را مجاز میدانست، و آن هم کدِ نسخهی لینوکس بود نه نسخهی اصلی DOS، بهسبب مجوز جداگانهی کتابخانهی صوتی DMX. تغییر مجوز به GPL نزدیک دو سال بعد، در ۳ اکتبر ۱۹۹۹، رخ داد. همین تاریخ دوم است که اهمیت دارد: DOOM را از چیزی که میشد خواند به چیزی بدل کرد که میشد قانوناً از نو ساخت. به همین دلیل است که این بازی همچنان در جاهای نامنتظر سر بر میآورد.
پلِ میان این دو، کامپایلری بود که عمداً قدیمی انتخاب شده بود. ading2210 از Emscripten 1.39.20 — نسخهای از ۲۰۲۰ — استفاده کرد، چون خروجیاش asm.js است نه WebAssembly. Emscripten امروزی WebAssembly تولید میکند و PDF محیط اجرای WebAssembly ندارد. asm.js گویشی محدود از JavaScript معمولی است، پس هرجا JavaScript اجرا شود، اجرا میشود. بازگشت به ابزار قدیمی نوستالژی نبود؛ تنها راه ورود بود.
میماند نمایش، بخشی که مردم را به خندهی بلند میاندازد. PDF نه بوم دارد، نه بافر تصویر، نه هیچ چیزی که بتوان روی آن پیکسل کشید. اما فیلدهای فرم دارد. بنابراین خروجی ۳۲۰×۲۰۰ بازی با نویسههای ASCII ترسیم میشود — برای هر سطر صفحه یک فیلد متنی، در شش سایهی خاکستری — و به همان سرعتی تازه میشود که بتوان آن متن را بازنویسی کرد، یعنی تقریباً ۸۰ میلیثانیه برای هر فریم. ورودی هم از همان راه میآید: فیلدها و دکمههایی که موتور PDF از پیش با آنها آشناست. شما به معنای واقعی کلمه درون یک فرمِ پرکردنی DOOM بازی میکنید.
کند اجرا میشود. تکرنگ است. کاملاً قابل بازی است، مانند کدی که بر آن استوار است زیر مجوز GPL v2 منتشر شده، و میتوانید خودتان در مرورگری مبتنی بر Chromium امتحانش کنید. نسخهی ساختهشده حتی اجازه میدهد فایل WAD خودتان را جای بدهید.
سپس لینوکس را در آن بالا آورد
چند هفته بعد همان توسعهدهنده linuxpdf را منتشر کرد: یک هستهی کامل لینوکس که درون یک فایل PDF بالا میآید، با ترجمهی شبیهساز RISC-V به نام TinyEMU با همان ترفند asm.js. بالا آمدن هسته ۳۰ تا ۶۰ ثانیه طول میکشد — نویسنده آن را بیش از صد برابر کندتر از سختافزار واقعی میداند — و با صفحهکلیدی مجازی که از دکمههای PDF ساخته شده کنترل میشود.
DOOM درون یک سند شوخی است. پردازندهای شبیهسازیشده که درون یک سند سیستمعامل بالا میآورد، دیگر یک استدلال است. جایی میان این دو، ماجرا دیگر دربارهی DOOM نیست.
بخشی که خندهدار نیست
این فکر ارزش درنگ دارد: هیچچیز در doompdf سوءاستفاده از آسیبپذیری نیست. هیچ حفرهای یافت نشد، چیزی شکسته نشد، هیچ رخنهی امنیتی در کار نبود. تکتک چیزهایی که به کار میگیرد، قابلیتی مستند و عمدی در مشخصات PDF است که دقیقاً طبق طراحی کار میکند.

یعنی همان تواناییای که به یک PDF اجازه میدهد بازی تیراندازی ۱۹۹۳ را اجرا کند، در فاکتوری هم هست که فردا باز میکنید. کمین نکرده، پنهان نیست — فقط آنجاست، بیاستفاده، چون بیشتر سندها دلیلی برای استفاده از آن ندارند.
این روایت صادقانهی ماجراست و از دو سو میبُرد. همان استدلالی که میگوید «سند میتواند کد اجرا کند، پس مراقب باش»، باید بپذیرد که جهانِ آن کد چقدر تنگ است.
یک اسکریپت درون PDF چه میتواند و چه نمیتواند
اینجاست که بیشتر نوشتهها دربارهی doompdf مبهم میشوند، پس دقیق باشیم. پاسخ کاملاً به این بستگی دارد که فایل را با چه چیزی باز کردهاید — و دو حالت رایج بسیار متفاوتاند.
| توانایی | نمایشگر مرورگر (Chrome، Edge، Firefox) | Adobe Acrobat Reader |
|---|---|---|
| اجرای اسکریپت هنگام باز شدن | بله | بله، مگر غیرفعال شده باشد |
| خواندن و نوشتن فیلدهای فرم | بله | بله |
| خواندن کوکیها یا حافظهی مرورگر | خیر | موضوعیت ندارد |
| دسترسی به صفحهی HTML پیرامون (DOM) | خیر | موضوعیت ندارد |
| ارسال درخواست شبکه | بسیار محدود | گستردهتر — پیکسلهای ردیابی و نشت NTLM اینجا زندگی میکردند |
| دسترسی به فایلهای محلی | خیر | محدود، اما سطح API بسیار بزرگتر |
| اجرای برنامههای بیرونی یا پیوستها | خیر | با تأیید — تاریخاً راهِ سندهای مخرب |
این جدول را از سمت درست بخوانید. در مرورگر، PDF اسکریپتدار در جعبهای کوچک و کسلکننده اجرا میشود: بدون کوکی، بدون حافظه، بدون دسترسی به صفحهی پیرامون. دقیقاً به همین دلیل doompdf یک کنجکاوی است نه یک رخداد امنیتی، و به همین دلیل «DOOM در PDF اجرا میشود» دلیلی برای ترس از PDF نیست.
ستون جالب، ستون خوانندهی رومیزی است. تمام رابط برنامهنویسی JavaScript که مشخصات توصیف میکند در اختیار اوست، چون قرار است سندهای واقعی کسبوکار را اجرا کند. این همان محیطی است که میتوان به سند گفت لحظهی باز شدن خبر بدهد، بسته به خواننده رفتار متفاوتی نشان دهد، یا پیشنهاد کند چیزی را که با خود آورده باز کند.
پس سه چیز فارغ از برنامه درست میماند و همینها ارزش درونیکردن دارند.
- یک PDF میتواند دستورهایی داشته باشد که در همان لحظهی باز شدن اجرا میشوند، پیش از آنکه چیزی خوانده باشید.
- یک PDF میتواند بسته به نرمافزاری که بازش میکند رفتار متفاوتی داشته باشد: فایلی که شما میبینید لزوماً همانی نیست که همکارتان میبیند.
- یک PDF بیش از آنچه نشان میدهد حمل میکند: پیوستها، لایههای پنهان، تاریخچهی ویرایش و فرادادههایی که هرگز قصد فرستادنشان را نداشتهاید.
هیچیک از اینها PDF را به معنای روزمره خطرناک نمیکند. این ماه دهها فایل باز خواهید کرد و همه بیمشکل خواهند بود. اما یعنی مدل ذهنیای که بیشترمان با خود داریم — «فقط یک سند است» — به شکلی نادرست است که گاهی اهمیت پیدا میکند.
تنظیمی که تقریباً کسی از آن خبر ندارد
توصیهی استاندارد این است: «JavaScript را در خوانندهی PDF خاموش کنید»، و توصیهی خوبی است. اما بهتنهایی ناقص است — چون بیشتر مردم دیگر PDF را در خوانندهی PDF باز نمیکنند. آن را در زبانهی مرورگر باز میکنند و مرورگر کلید جداگانهی خودش را دارد.
فایرفاکس با اسکریپتنویسی PDF روشن عرضه میشود. نام تنظیم pdfjs.enableScripting در about:config است؛ تا فایرفاکس ۸۷ مقدارش false بود و از فایرفاکس ۸۸ true است. کلید عمومی javascript.enabled به آن کاری ندارد: نمایشگر PDF جهانی جداست با تنظیمی جدا.
کروم و اِج اصلاً کلید اختصاصی برای اسکریپت در PDF ندارند. اسکریپت درون PDF تابع مجوز JavaScript همان سایتی است که فایل از آن آمده؛ میتوان آن را برای هر سایت از کنترلهای کنار نوار نشانی خاموش کرد یا بهطور کلی از chrome://settings/content/javascript — ابزاری بهمراتب خشنتر.
Adobe Acrobat Reader همان کلیدی را دارد که همه در ذهن دارند: ترجیحات ← JavaScript ← فعالسازی JavaScript در Acrobat. همین تیک است که برداشتنش میارزد، چون Acrobat خوانندهای است با رابط برنامهنویسی بزرگ و تقریباً هیچکس در کار روزمره آگاهانه از PDF اسکریپتدار استفاده نمیکند.
در عمل: خاموشکردن آن در Acrobat و کاری نداشتن به مرورگر انتخابی معقول و متناسب است. اما گمانکردن اینکه همهجا خاموشش کردهاید، در حالی که فقط در Acrobat این کار را کردهاید، معقول نیست.
با این اطلاعات چه کنیم
پاسخ عملی کوچک است و ارزش آن ده دقیقه را دارد.
JavaScript را در خوانندهی رومیزی خاموش کنید. در Acrobat Reader: ترجیحات ← JavaScript. این کار یک دستهی کامل از خطر را حذف میکند و هیچ هزینهای ندارد جز — باید اعتراف کرد — امکان بازی DOOM در یک فیلد فرم.
خواننده را بهروز نگه دارید. اسکریپت یک راه ورود است. ایرادهای موجود در کدی که قلمها و تصویرها را رمزگشایی میکند راه دیگری است، و همانهاست که بهروزرسانیها ترمیم میکنند — تاریخاً این راهِ رایجتر هم هست.
با سندهای غیرمنتظره مثل چیزی غیرمنتظره برخورد کنید. فاکتوری از شرکتی که هرگز از آن خرید نکردهاید، در هر قالبی که برسد، ارزش یک لحظه تأمل دارد. این از هر تنظیمی باارزشتر است.
ببینید این سه چه اشتراکی دارند: هیچکدام از شما نمیخواهد استفاده از PDF را کنار بگذارید یا به سندها بهطور کلی بدگمان باشید. اینها معادل قفلکردن درِ خانهاند — ارزان، کسلکننده و دقیقاً از آن رو معقول که خطر کوچک است اما صفر نیست.
چرا این پروژه شایستهی توجهی بود که گرفت
آسان بود که doompdf را در پوشهی «کنجکاویهای اینترنتی» بگذاریم و رد شویم. من میگویم از این مفیدتر است، به دلیلی که هیچ ربطی به نمایشِ امنیت ندارد.
درک بیشتر مردم از قالبهای فایل تماماً بر پایهی کاربردشان ساخته شده است. سند برای خواندن است. صفحهگسترده برای عدد. تصویر برای دیدن. این مدل تقریباً همیشه کار میکند و دقیقاً به همین سبب جابهجا کردنش اینقدر سخت است — و به همین سبب توضیح «PDF میتواند محتوای فعال داشته باشد» معمولاً با تردیدی مؤدبانه روبهرو میشود.
یک بازی قابلاجرا درون یک سند، در ده ثانیه کاری را میکند که یک مقاله با هزار کلمه بهسختی میکند. ادعایی انتزاعی را با چیزی که میشود رویش کلیک کرد جایگزین میکند.
و نکتهی عمیقتر بسیار فراتر از PDF میرود. قالبها در طول دههها قابلیت انباشته میکنند. هر افزوده برای کسی که مسئلهای واقعی حل میکرد منطقی بوده — اعتبارسنجی فرم واقعاً مفید است، سندی که حساب خودش را وارسی کند هم همینطور. نتیجه آنکه چیزهای عادیای که هر روز مبادله میکنیم بهمراتب تواناتر از نامشاناند. و توانایی، وقتی یکبار وارد مشخصات شد، در دسترس هرکسی است که آن مشخصات را بخواند.
از این همه، برای کار روزمره چه میماند
هیچچیز اینجا استدلالی علیه PDF نیست. هنوز بهترین قالب برای فرستادن سندی است که همهجا، روی هر دستگاهی و سالها بعد یکسان دیده شود. این مسئلهای واقعاً دشوار است و PDF حلش کرده. همان قابلیتهایی که doompdf را ممکن میکنند، فرم مالیاتی پرکردنی را هم ممکن میکنند.
این استدلالی است به سود اینکه بدانید با چه سروکار دارید. همان انعطافی که به سند اجازه میدهد یک بازی حمل کند، به او اجازه میدهد اسکریپت، پیوست، لایهی پنهان و فرادادهای را حمل کند که هرگز قصد فرستادنش را نداشتهاید. ارزش فهمیدن دارند و هیچکدام دلیل نگرانی نیستند.
و بخشی از دلیل اینکه PDF Manipulator تماماً روی رایانهی خودتان اجرا میشود همین است. هنگام ادغام، تقسیم یا تبدیل فایل، هرچه طرفهای کمتری در کار باشند بهتر — نه از آن رو که سرویسهای آنلاین شرورند، بلکه از آن رو که سندی که هرگز از دستگاه شما بیرون نرفته، بهمراتب سادهتر از سندی است که روی سرور کسی دیگر بوده.
با فایلهای PDF خود کاملاً آفلاین کار کنید — PDF Manipulator رایگان است →


منابع
- ading2210، doompdf در GitHub — کد منبع و توضیح فنی؛ Emscripten 1.39.20، خروجی ۳۲۰×۲۰۰ در شش سایه، حدود ۸۰ میلیثانیه برای هر فریم، مجوز GPL v2
- ading2210، linuxpdf در GitHub — لینوکس روی شبیهساز RISC-V به نام TinyEMU درون PDF، بالا آمدن در ۳۰ تا ۶۰ ثانیه
- نسخهی قابل بازی (مرورگرهای مبتنی بر Chromium)
- Eric Lawrence، Browser Security Bugs that Aren’t: JavaScript in PDF — موتورهای PDF مرورگرها چه چیزی را برای اسکریپتها مجاز میدانند و چه چیزی را نه
- Adobe، Restrict JavaScript API access in Acrobat
- DoomWiki، Licences — انتشار کد در ۲۳ دسامبر ۱۹۹۷، تغییر مجوز به GPL در ۳ اکتبر ۱۹۹۹
- The Register، It’s Doom … running in a PDF file
- Ars Technica، This PDF contains a playable copy of Doom
