نامهای عاشقانه به قلعه بُعدِ برتر

هرچه بیشتر درباره وب یاد میگیرم، بیشتر قدردانِ چیزهایی میشوم که قبلتر وجود داشتند. واقعاً ما روی شانههای غولها ایستادهایم. در هفتهی گذشته، خوشحال بودم (بالاخره) عضو ARPA شوم در SDF، یک سیستم UNIX عمومیِ غیرانتفاعی و جامعهی آنلاین که از سال 1987 بهصورت پیوسته در حال فعالیت است.
اما SDF چیست؟ برای پاسخ به آن، باید چهار دهه به عقب برگردیم و درباره دوران BBS صحبت کنیم.
سیستمهای تابلوی اعلانات
این 16 ژوئن 1987 است. Ted Uhlemann («iczer») یک مودم 300-baud[1] مربوط به Apple IIe را به یک خط تلفن وصل میکند که مادرش تازه برای تولدش به او داده؛ و در حال اجرای Magic City Micro-BBS (نوشتهشده با Applesoft BASIC) است. او آن را به نام SDF-1 و به افتخار انیمهی موردعلاقهاش میگذارد، امیدوار است طرفداران «انیمه، موسیقی صنعتی و Church of the SubGenius» را جذب کند؛ طبق بازخوانیِ سیاُمین سالگرد توسط Stephen Jones. سختافزار اولیه شامل یک مودم 1200bps و دو درایو فلاپی است که هرکدام 280 کیلوبایت ظرفیت دارند.
این دقیقاً آغازِ SDF بود.
SDF خودش را «یک پلتفرم اجتماعی برای الهامبخشی، تسهیل و پیادهسازی ایدههای جدید» توصیف میکند. این یک ماشین NetBSD چندکاربره است که تنها با کمک اعضایش بهعنوان یک سازمان غیرانتفاعی 501(c)(7) تأمین مالی میشود؛ جایی که دهها هزار نفر حساب کاربری دارند. نام آن از انیمهی Super Dimension Fortress Macross (که در غرب بخشی از Robotech شناخته میشود) آمده و سیستم از یک BBS برای طرفداران انیمهی ژاپنی شروع شد. دوران BBS در SDF را میتوان در مستند هشتقسمتی 2004 در YouTube با عنوان BBS: The Documentary دید؛ مستندی که شامل یک مصاحبهی ضبطشده با Stephen Jones، مدیر سیستمِ قدیمیِ SDF است.
سیستمهای تابلوی اعلانات پیش از اینترنتِ مدرن وجود داشتند و بهطور قابلبحث، رایانههای شخصی را از کیتهای نوظهور و گرانقیمت به ماشینهای بسیار محبوبتری تبدیل کردند. BBSها همان چیزی بودند که رایانههای شخصی را در دههی 1980 و اوایل دههی 1990 به دروازههای ضروری برای ارتباطات جهانی و محلی تبدیل کردند. آنها ثابت میکردند که کامپیوتر برای ارتباط برقرار کردن با دیگران است.
در آن زمان موتور جستوجویی وجود نداشت، بنابراین باید در مجلههای کامپیوتری یا فایلهای متنی از سایر تابلوها دنبال یک BBS میگشتید. «آدرس وبسایت» در واقع یک شماره تلفن محلیِ هفترقمی بود. شما یک برنامه ترمینال روی رایانهتان باز میکردید و یک دستور تایپ میکردید تا مودمتان شماره تلفن BBS را شمارهگیری کند. چون از خط تلفن منزل شما استفاده میکرد، هیچکس دیگری در خانه نمیتوانست وقتی شما آنلاین بودید از تلفن استفاده کند. شما صدای شمارهگیری فیزیکیِ کامپیوتر را گوش میدادید؛ بعد هم جیغِ آیکونیک و تند و خشخشِ ایستا دو مودم که با هم حرف میزدند.
در اوج محبوبیت، بیش از 150,000 BBS در آمریکای شمالی فعال بودند. تا سال 2005 فقط چند صدتا باقی مانده بود.
در یک مصاحبه bsdtalk در سال 2006، یکی از اعضای قدیمی خلاصه کرد که چه چیزی باعث میشود اینجا دوام بیاورد:
«SDF بیشتر از یک حساب شِل است؛ یک جامعه از آدمهاست که از روشهای مختلفی که SDF فراهم میکند با هم ارتباط برقرار میکنند... چیزی که SDF را خاص میکند این است که مثل یک محیط محاسباتی در روزهای اولیهی اینترنت اداره میشود. اصلاً شرکتی نیست.»
یک نظرسنجیِ 2019 از سوی یک پژوهشگر دانشگاهی درباره سیستمهای UNIX با دسترسی عمومی، History, Evolution and Future of Public Access UNIX که خودِ آن روی SDF میزبانی میشود، سیستم مدرن را «یک جامعهی اجتماعیِ کاملاً تعریفشده» توصیف میکند و اضافه میکند که SDF گروههای علاقهمندیِ ویژه را برای رادیوی آماتوری (SDFARC)، علاقهمندان پایتون، گوفِر و بازیکنان Minecraft در کنار «هنرمندان دیجیتال، تاریخنگاران کامپیوتر، توسعهدهندگان وب، گیمرها و البته بسیاری، بسیاری برنامهنویسها» پشتیبانی میکند. تور تصویری خودِ SDF سختافزار را سالبهسال تا 1985 مستند میکند، از جمله یک دوره در موزه تلفن و ماشینهایی که امروز هم در حال اجرا هستند.
امروز شبکه شامل سرورهای NetBSD روی سختافزار DEC Alpha و AMD Opteron است، بهعلاوه محیطهای زندهی رتروکامپیوتینگ: یک سیستم TOPS-20 (twenex.org، که Panda Distribution TOPS-20 را روی دو XKL TOAD-2 اجرا میکند)، یک ماشین Symbolics Genera و یک سیستم ITS. حسابهای رایگان روی همهی آنها در دسترس است.
در چهار دههی گذشته، SDF از خرابیهای سختافزاری، DDoSهای بیشمار، قطع دسترسی توسط ISP خودش و چندین جابهجایی در سراسر ایالات متحده جان سالم به در برده است. هرگز تجاری نشده و در آن مدت هم پایگاه کاربرانش را از دست نداده است. Jones که هنوز هم دههها بعد SDF را اجرا میکند، در نامهی سیاُمین سالگردش نوشت:
«برخی از آدمها امروز ممکن است اینجا بیایند و ما را قدیمی و «رترو» ببینند. اما اگر درگیرش شوید، میبینید که با ایدههای جدید کاملاً زنده است.»
خدمات ارائهشده توسط SDF
SDF از روزهای BBS خود خیلی راه را طی کرده، هرچند هنوز یکی از آخرین جاهایی است که دسترسی رایگانِ شمارهگیری ارائه میدهد. وقتی در SDF عضو میشوید، تعداد زیادی سرویس میگیرید—تا حدی شبیه گرفتن یک حساب Tildeverse یا omg.lol، و البته قبلتر از هر دوی آنها.
از شِل شروع میکنید. اجرای دستور ssh you@tty.sdf.org شما را در NetBSD قرار میدهد با چیزهای معمولی مثل bash، ksh، tcsh، rc و zsh؛ و ویرایشگرهایی از ed تا emacs. و ping، traceroute، dig، whois و finger و غیره.
یک صفحه وب مخصوص خودتان میگیرید؛ اجرای mkhomepg در شِل یک پوشهی ~/html میسازد و میپرسد کدام URL را میخواهید. فایلهایتان را در ~/html اضافه میکنید و سایت بلافاصله در you.sdf.org فعال میشود. اعضای ARPA میتوانند از بین حدود 60 گزینه یک دامنهی دلخواه (وانیتی) انتخاب کنند (pdp10.org، twenex.org، chaosnet.org، freak.net، multics.org...). برای فهرست، wiki.sdf.org را ببینید. CGI آماده و بدون دردسر کار میکند. شِل/awk/sed برای همه، و دسترسی کامل php/perl/python/ruby برای اعضای ARPA.
پروتکلهای Gopher و Gemini معمولاً بیشتر توسط کاربران SDF استفاده میشوند. mkgopher را در شِل اجرا کنید و setup را انتخاب کنید. ~/gopher را میسازد (یک symlink به داخل /ftp/pub/users/you) که هم بهعنوان gopher://sdf.org/1/users/you و هم gemini://sdf.org/users/you سرو میشود. یک دایرکتوری، دو پروتکل! یک gophermap بنویسید یا فایلهای .gmi را اضافه کنید. gopher setup و gemini setup را ببینید.
و این فقط نوکِ کوه یخ است:
| سرویس | کجا |
|---|---|
| IRC | irc.sdf.org :6667 |
| Jabber/XMPP | jabber.sdf.org |
| Matrix | matrix.sdf.org |
| Gitea | git.sdf.org |
| Mastodon | mastodon.sdf.org |
| PixelFed | pixelfed.sdf.org |
| PeerTube | toobnix.org |
| TT-RSS | ttrss.sdf.org |
| Lemmy | lemmy.sdf.org |
| Gallery | sdf.org/g |
| Deskshots | deskshots.org |
| Jitsi | jitsi.sdf.org |
| aNONradio | anonradio.net |
| Minecraft | mc.sdf.org |
| BZFlag | sdf.org:5154 |
| SDFMud | sdf.org/mud |
| TOPS-20 | twenex.org |
چگونه عضو شویم
در ابتدا، تنها راهِ عضویت در SDF و تأیید شدن این بود که یک دلار را بهصورت فیزیکی به صندوق پستیشان در Seattle بفرستید همراه با نام کاربریتان. این روش هوشمندانهای بود برای جلوگیری از هرزنامه و سوءاستفاده.
امروزه، خوشبختانه، فقط میتوانید از طریق Paypal کمک مالی کنید و همین کل روند را خیلی آسانتر میکند.
فکر میکنم یکی از جالبترین چیزها درباره SDF، عضویت مادامالعمر ARPA است. با یک پرداخت یکباره ۳۶ دلار آمریکا، شما:
- ابزارهای خروجی:
telnet،ssh،sftp،ftp،snarf،wget،ytalk، IRC خارجی. اکانتهای رایگان فقط ورودی هستند؛ ARPA شبکه را از هر دو طرف باز میکند - انتقال فایل:
scp/sftpو SSH غیرتعاملی:ssh-copy-idفعال است - توسعه:
gcc،perl،php،python،ruby،elispروی دستگاه - CGI کامل:
php/perl/python/rubyروی سایت شما - VoIP: تماس اینترنتی، صندوق صوتی، کنفرانس (تماس PSTN یک افزودنی ۱۵ دلار در هر فصل است، با گزینه DID واقعی)
- UUCP + ClariNET: فیدهای ایمیل و news از طریق TCP یا dialup
- حق رأی: روی ویژگیهای سیستم و سیاستها
- سهمیهها: حدود ۱۵۰ MB / ۵۰۰۰ فایل برای هر کدام از home، mail، webspace، gopherspace
نهتنها همه موارد بالا را برای همیشه دریافت میکنید، بلکه دارید از یک جامعه شبکهای پشتیبانی میکنید که از زمانی که من زندهام هم بیشتر وجود داشته!
امتیاز اضافه: ساخت یک کتاب مهمان Perl CGI در SDF
آن زمانها، برای افزودن قابلیت به وبسایتتان، اسکریپتهایی مینوشتید که از طریق پروتکل Common Gateway Interface (CGI) با یک وبسرور تعامل میکردند. در اواخر دهه ۱۹۹۰ و اوایل دهه ۲۰۰۰، این فناوری اصلی بود که وب جهانی (World Wide Web) را از صفحههای ثابت HTML به وبسایتهای پویا و تعاملی تبدیل میکرد.
متأسفانه در توسعه وبِ امروزی خیلی استفاده نمیشوند و فناوریهای منسوخ محسوب میشوند و از آنها دلسرد میکنند. چون CGI سنتی برای هر کلیکِ بازدیدکننده، یک فرایند کاملاً جدید از سیستمعامل را ایجاد میکند. بنابراین در وبسایتهای شلوغ، حجم عظیمی از حافظه سرور مصرف میکردند و عملکرد را تا حدی کند میکردند که انگار از حرکت میماند.
اما وقتی دارید یک وبسایت شخصی کوچک میسازید، چیزهایی مثل «مقیاسپذیری» و «مصرف کارآمد منابع» را میشود دور انداخت! به چه کسی مربوط است؟ از آنجا که به عنوان یک عضو ARPA به Perl CGI دسترسی دارم، تصمیم گرفتم در صفحه کوچک SDF خودم یک کتاب مهمان ساده درست کنم. اینطوری آن را کنار هم گذاشتم.
1. فهمیدن دایرکتوریهای SDF
در SDF، ریشهی وبسایت شما دایرکتوری ~/html است، اما این دایرکتوری home شما نیست. در واقع یک symlink به /www/<a>/<b>/<username> است (دایرکتوریهای والد از نام کاربری شما میآیند، پس مال من /www/af/b/bren است). دایرکتوری home واقعی شما جایی شبیه /sdf/arpa/af/b/bren است. حالا نمیخواهید فایل داده داخل فولدرِ ~/html که عمومی سرو میشود زندگی کند، جایی که یک بازدیدکننده بتواند آن را مستقیم درخواست کند. در عوض، یک سطح بالاتر، بیرون از ریشه وب نگهش دارید:
/sdf/arpa/af/b/bren/guestbook.dat <- data file, NOT web-accessible /www/af/b/bren/guestbook.cgi <- the script itself, lives in ~/html
همچنین، $ENV{HOME} وقتی اسکریپت CGI شما زیر suexec اجرا میشود تنظیم نمیشود، پس نمیتوانید به مسیرهای نسبی مثل ~ داخل اسکریپت تکیه کنید. من فقط مسیر مطلقِ فایل داده را به صورت hardcode کردم.
2. نوشتن اسکریپت
برای این کار از Perl هستهای (core) و Fcntl برای قفلگذاری فایل استفاده میکنم (اگر روزی دو بازدیدکننده همزمان وارد شده باشند)، ولی تقریباً همین است. اسکریپت $ENV{REQUEST_METHOD} را میخواند، بدنه فرم POSTشده را دستی تجزیه میکند (هیچ CGI.pmای، چون منسوخ شده)، طول نام/پیام را اعتبارسنجی میکند و سپس یک خط به فایل اضافه میکند:
use strict;
use warnings;
use Fcntl qw(:flock);
my $DATA_FILE = "/sdf/arpa/af/b/bren/guestbook.dat";
sub add_entry {
my ($name, $message, $url) = @_;
my $ts = scalar localtime;
my $enc_message = $message;
$enc_message =~ s/\\/\\\\/g;
$enc_message =~ s/\n/\\n/g;
open(my $fh, '>>', $DATA_FILE) or return;
flock($fh, LOCK_EX);
print $fh join("\x01", $ts, $name, $enc_message, $url) . "\n";
flock($fh, LOCK_UN);
close($fh);
}هر ورودی فقط یک خط است، timestamp \x01 name \x01 message \x01 url، و از کاراکتر کنترلی \x01 که در غیر این صورت استفاده نمیشود بهعنوان جداکننده فیلد استفاده میکند؛ چون این کار تضمین میکند نامها یا پیامهایی که شامل علائم نگارشی معمول هستند، هنگام تجزیه به هم نریزند. خطجدیدهای داخل یک پیام با یک \n واقعی در هنگام نوشتن escape میشوند و هنگام خواندن دوباره بدون escape برمیگردند؛ به این ترتیب پیامهای چندخطی هم به تکخط تبدیل میشوند.
یک فیلد honeypot هم وجود دارد، website، که با CSS از دید بازدیدکنندگان پنهان میشود. اگر پر شود، ارسال نادیده گرفته میشود، اما ربات همچنان «Thanks for signing!» را میبیند.
3. قفل کردن فایل داده
از آنجا که فایل داده باید جایی باشد که آپاچی بتواند به آن دسترسی داشته باشد (در مورد من، نمیخواستم زیاد روی symlinkها فکر کنم)، یک .htaccess در ~/html اضافه کنید:
<Files "guestbook.dat">
Order allow,deny
Deny from all
</Files>4. آپلود کردن و اجراییاش کردن
SDF از اسکریپتهای CGI میخواهد که (1) به .cgi ختم شوند و (2) اجرایی باشند. هیچ الزام دایرکتوریِ cgi-bin وجود ندارد، پس میشود هر جای ~/html گذاشت:
scp guestbook.cgi bren.sdf.org:html/ ssh bren.sdf.org chmod 755 html/guestbook.cgi mkhomepg -p
mkhomepg -p بهدرستی مجوزهای صفحه اصلیتان را به تنظیمات پیشفرض امنِ مورد انتظار SDF برمیگرداند.
5. سر بزنید
تمام! guestbook.cgi همان صفحه را برای هر دو GET (نمایش فرم و آخرین ۵۰ ورودی) و POST (اعتبارسنجی و ذخیره مورد جدید) نمایش میدهد. پایگاهداده، فریمورک یا بیلد ندارید. تا استانداردهای سال ۲۰۲۶ کمی بدقواره است، و من عاشقش هستم. اگر خواستید امضا کنید: bren.sdf.org/guestbook.cgi (توجه: http است نه https).
امتیاز اضافه: ساخت یک وبسایت سازگار با Dillo
در نهایت، از پست وبلاگ Sunny با عنوان on positive, human-made software الهام گرفتم؛ جایی که مرورگر اینترنت Dillo را هم فهرست کرده بود.
آن زمانها، وقتی تنها کامپیوترم یک Intel Core 2 Duo خیلی کند بود، یادم هست دنبال مرورگرهای سبک میگشتم تا تجربه وبگردی کمتر دردناک باشد. Dillo قطعاً یکی از آنهاست! «حجم کُدِ آن در حال حاضر ۰.۲٪ اندازه Chromium است» و استفادهاش از حافظه هم واقعاً خیلی پایین است.
بدیهی است که این مزایا هزینه هم دارد. به خاطر محدودیتهایش، بخش زیادی از وب با Dillo درست رندر نمیشود یا درست کار نمیکند. اما به نظر من این یک ویژگی است. یکی از بهترین راههایی که میتوانیم مطمئن شویم صفحات وب ما اصول smol web را رعایت میکنند، در عین حال که کد منبعی داریم که برای مبتدیها خواندنش آسان است، این است که سایتهایمان را با Dillo سازگار کنیم.
اما این دقیقاً به چه معناست؟
خب، Dillo یک زیرمجموعه از HTML 4.01 را با تعدادی المان HTML5 لایهگذاریشده پشتیبانی میکند و یک زیرمجموعه از CSS 2.1 را با تعدادی المان CSS3 لایهگذاریشده. هیچ JavaScriptی وجود ندارد.
<script> و همه هندلرهای رویداد درونخطی (onclick، و …) دور ریخته میشوند. frameset/frame/iframe پشتیبانی رندر ندارند. هیچ پشتیبانیای هم برای هیچ <canvas> یا video، audio، source، embed، object برای پخش وجود ندارد.
در مورد CSS و استایلها، هیچ پشتیبانیای از متغیرهای CSS وجود ندارد (var()). همچنین هیچ flexboxای و هیچ CSS gridای هم وجود ندارد. قوانین Grid هم فقط نادیده گرفته میشوند. مجبورید چیدمانها را با (gulp) table و float انجام دهید، به جای آن.
ضمناً فونتهای وب سفارشی با @font-face هم ندارید، چون فونتها به پنج خانواده عمومی CSS حل میشوند: serif، sans-serif، monospace، cursive، و fantasy که همگی در تنظیمات کاربرِ dillorc (font_serif، font_sans، و …) تعیین میشوند. Dillo توانایی بارگذاری فایلهای مشخص فونت وب را ندارد.
این را با کمی احتیاط در نظر بگیرید، چون من واقعاً نتوانستم یک جدول سازگاری «معتبرِ» (canonical) پیدا کنم. توسعهدهندگان Dillo از طریق manual، changelog و bug tracker ارتباط برقرار میکنند.
نتیجهگیری
جالب است؛ هرچه بیشتر درباره توسعه وب یاد میگیرم، بیشتر به سمت چیزهای ساده و «برگردگشته به زمان قدیم» میروم. فکر میکنم منطقی است—کد خوب، کدِ بیاضافه است. هرچه بتوانید به سمتِ حداقلِ رابط کاربری نزدیکتر شوید، رابط کاربری بهتر است. این یک جنبه بهطرز شگفتانگیزی متناقض از برنامهنویسی و کار کردن با کامپیوترهاست. اینها همیشه ماشینهایی با محدودیتهای متناهیاند—مثل خود ما—و باید هم حواسمان بهش باشد و هم از آن به نفع خودمان استفاده کنیم.
- نرخ بُود (baud rate) سرعتی است که یک ترمینال سختافزاری یا کنسول سریال از طریق آن ارتباط برقرار میکند و بر حسب تعداد تغییرات سیگنال (نمادها) که در هر ثانیه ارسال میشوند اندازهگیری میشود. در 300 بُود، یک ترمینال در هر ثانیه 30 کاراکتر نمایش میدهد. این تقریباً سرعت یک تایپیست سریع است. بهجای اینکه متن فوراً ظاهر شود، میتوانید بهصورت فیزیکی حروف را ببینید که یکییکی و خطبهخط روی صفحه ظاهر میشوند. ↩︎