HTML encode करें

टेक्स्ट चिपकाइए और उसे उन अक्षरों के escape रूपों के साथ वापस पाइए जो बदल देते हैं कि दस्तावेज़ कैसे पढ़ा जाएगा। यही वह क़दम है जो किसी और के लिखे टेक्स्ट को सामग्री बनाता है, ढाँचा नहीं, और यही वह जगह है जहाँ एक भूला हुआ प्रतिस्थापन किसी टिप्पणी-खाने को सुरक्षा की समस्या में बदल देता है। गणना इसी पन्ने पर होती है।

पहला वही करता है जो कोई template इंजन करता है। दूसरा उस शृंखला के लिए है जो UTF-8 साफ़-साफ़ नहीं सँभालती।

नतीजा

आप लिखते जाइए, जवाब यहाँ आता जाएगा।

  • कहाँ चलता है

    कुछ भी अपलोड नहीं होता, क्योंकि कोई फ़ाइल है ही नहीं — गणना इसी पन्ने में होती है।

  • न कतार, न खाता

    यह उतनी ही तेज़ी से जवाब देता है जितनी आपकी मशीन देती है, और कभी नहीं पूछता कि आप कौन हैं।

  • जितनी बार चाहें

    न कुछ गिना जाता है, न कोई सीमा है — दोबारा जवाब देने में हमारा कुछ ख़र्च नहीं होता।

काम कैसे करता है

  1. टेक्स्ट या markup का टुकड़ा चिपकाइए।
  2. चुनिए कि कहाँ तक escape करना है: सिर्फ़ वह जो पढ़ाई बदलता है, या उसके साथ ASCII से ऊपर सब कुछ।
  3. नतीजा कॉपी कर लीजिए। वह डिवाइस से बाहर नहीं गया।

वे पाँच अक्षर जिनके इर्द-गिर्द यह सब है

HTML के parser को बहुत ही कम अक्षरों की परवाह है। छोटे और बड़े का चिह्न कोई टैग खोलते और बंद करते हैं, ampersand किसी अक्षर-संदर्भ की शुरुआत करता है, और किसी attribute के मान के भीतर दोहरा तथा इकहरा उद्धरण-चिह्न उसे ख़त्म कर देते हैं। ये पाँच हैं, और बाक़ी सब सामान्य सामग्री है।

इसीलिए संयत सेटिंग ठीक इन्हीं पाँच को escape करती है और कुछ नहीं। जो encoder हर मात्रा को एक entity में बदल देता है वह ज़्यादा सुरक्षित नहीं है: वह सिर्फ़ चार-पाँच गुना लंबा और इंसानों के लिए अपठनीय नतीजा बनाता है, और बचाता ठीक उन्हीं हमलों से है जिनसे छोटा रूप बचाता है।

Ampersand पहले जाता है, वरना जाता ही नहीं

जो हाथ से प्रतिस्थापन कर रहा है उसे `&` से शुरू करना होगा। अगर उसकी बारी बाद में आई, तो encoder तब तक अपनी entity बना चुका होता है और हर एक का `&` दोबारा escape कर देता है: `<` `&lt;` बनता है और वह `&amp;lt;`, और पन्ना छोटे के चिह्न के बजाय `&lt;` टेक्स्ट दिखाता है।

घर की बनी escape-सुविधाओं में यह अब तक की सबसे आम ग़लती है, और उन गिनी-चुनी ग़लतियों में है जो नतीजे में नंगी आँख से पहचानी जा सकती हैं: अगर दूसरे entity-नामों के आगे `&amp;` दिखे तो क्रम ग़लत है। यह औज़ार प्रतिस्थापन एक ही चक्र में करता है, इसलिए यह समस्या हो ही नहीं सकती।

सामग्री और attribute एक चीज़ नहीं हैं

दो टैगों के बीच तीन प्रतिस्थापन काफ़ी हैं: छोटा, बड़ा और ampersand। किसी attribute के मान के भीतर उद्धरण-चिह्न भी जुड़ जाते हैं, क्योंकि वहाँ दोहरा उद्धरण मान को ख़त्म कर देता है और उसके बाद जो आए उसे parser एक और attribute की तरह पढ़ता है — किसी और के टैग में `onmouseover` घुसाने का चिरपरिचित रास्ता।

सबसे बुरी हालत बिना उद्धरण वाले attribute मान हैं, जिनकी HTML इजाज़त देता है: वहाँ मान ख़त्म करने के लिए एक स्पेस काफ़ी है, और escape करना ही नाकाफ़ी हो जाता है। व्यावहारिक नियम यह है कि attribute में हमेशा उद्धरण लगाइए और पाँचों अक्षर escape कीजिए, जो ठीक वही है जो इस पन्ने की सेटिंग करती है।

«ASCII से ऊपर सब कुछ» की ज़रूरत कब पड़ती है

दूसरी सेटिंग ASCII से बाहर के हर अक्षर को अंकों वाले संदर्भ के रूप में लिख देती है, इसलिए «क» `&#2325;` बन जाता है। सुरक्षा के लिए इससे कुछ नहीं मिलता और पठनीयता के लिए यह नुक़सान है: यह सिर्फ़ वहाँ काम आता है जहाँ शृंखला की कोई कड़ी UTF-8 नहीं सँभालती।

ऐसी कड़ियाँ आज भी हैं: पुराने ईमेल template, ऐसे तंत्रों को भेजे जाने वाले निर्यात जिनमें encoding जड़ी हुई है, कभी-कभी ग़लत collation वाला कोई कॉलम। अगर रास्ते में हिंदी अक्षर प्रश्नचिह्नों में या अजीब जोड़ों में बदल जाते हैं, तो अंकों वाला रूप एक ठोस चक्कर है। जहाँ शृंखला UTF-8 साफ़-साफ़ बोलती है, वहाँ यह फ़ालतू है।

हिंदी को पूरा escape करने पर वह कितना फूलता है

देवनागरी का एक अक्षर UTF-8 में तीन बाइट का है। अंकों वाले संदर्भ के रूप में वही अक्षर `&#2325;` बनता है, यानी आठ बाइट — ढाई गुने से ज़्यादा। पूरे हिंदी अनुच्छेद पर यह बहुत जल्दी दिखने लगता है, और वह भी बिना किसी सुरक्षा-लाभ के।

इसीलिए दूसरी सेटिंग को अंतिम उपाय की तरह लेना चाहिए, आदत की तरह नहीं। अगर किसी कड़ी में हिंदी टूट रही है तो सही सुधार उस कड़ी को UTF-8 पर लाना है; escape कर देना उस मरम्मत को टाल देता है और साथ में हर संदेश, हर ईमेल और हर निर्यात को ढाई गुना भारी कर देता है।

Escape निकास की सफ़ाई है, छन्ना नहीं

Escape एक ही जगह बचाता है: HTML में डालते समय। यह इनपुट की जाँच नहीं है और उसकी जगह नहीं लेता। जो दिखाते समय के बजाय सहेजते समय escape करता है उसके डेटाबेस में ऐसे मान बैठ जाते हैं जो किसी JSON जवाब में, किसी CSV निर्यात में या किसी ईमेल में `&amp;` बनकर दिखते हैं — यानी वहाँ जहाँ HTML का कोई लेना-देना ही नहीं था।

जो क्रम चलता है वह उलटा है: कच्चा सहेजिए और रेंडर करते समय उस ठोस मंज़िल के हिसाब से escape कीजिए। तब वही डेटा HTML में, JSON में और सादे टेक्स्ट वाले ईमेल में सही निकलता है, हर एक अपने नियमों के साथ, और किसी को अंदाज़ा नहीं लगाना पड़ता कि कोई फ़ील्ड किस हालत में है।

एक ही अक्षर लिखने के तीन तरीक़े

HTML `&amp;` जैसे नाम वाले संदर्भ, `&#38;` जैसे दशमलव और `&#x26;` जैसे hexadecimal — तीनों मानता है। तीनों एक ही अक्षर बताते हैं और parser तीनों क़बूल करता है। यह औज़ार उन पाँच निर्णायक अक्षरों के लिए नाम वाले संदर्भ बनाता है, क्योंकि वे स्रोत में पढ़े जाते हैं, और बाक़ी सबके लिए अंकों वाले।

दूसरों के बनाए नतीजे पढ़ते समय आपको तीनों मिली-जुली मिलेंगी, अक्सर एक ही फ़ाइल में, क्योंकि उन्हें अलग-अलग हिस्सों ने बनाया है। यह न त्रुटि है न किसी समस्या का संकेत: वह बस इतना कहता है कि उस दस्तावेज़ पर एक से ज़्यादा औज़ार चले हैं।

यहाँ `&#39;` क्यों बनता है, `&apos;` क्यों नहीं

इकहरे उद्धरण-चिह्न का एक नाम है, `&apos;`, पर वह XML से आता है और HTML5 से पहले औपचारिक रूप से HTML का हिस्सा नहीं था। HTML 4 में उसकी परिभाषा नहीं थी, इसलिए बहुत पुराने parser उसे हल करने के बजाय जस का तस छाप देते हैं।

अंकों वाला रूप `&#39;` कभी इस समस्या में नहीं पड़ा और हर जगह चलता है, इसलिए लगभग हर escape लाइब्रेरी का डिफ़ॉल्ट आज भी वही है। यह उन मामलों में से है जहाँ बीस साल पुरानी असंगति ने परिपाटी तय कर दी, भले उसका कारण मिट चुका हो।

HTML escape करने से JavaScript नहीं बचता

जो मान किसी `<script>` खंड के भीतर लिखा जाता है वह अब HTML के संदर्भ में नहीं बल्कि JavaScript के संदर्भ में है, और वहाँ दूसरे नियम चलते हैं। Entity के रूप में escape किया गया उद्धरण-चिह्न वहाँ मदद नहीं करता; और उलटा, HTML में निरापद कोई स्ट्रिंग स्क्रिप्ट को बंद कर सकती है।

यही बात किसी `href` के भीतर, किसी `style` के भीतर या किसी ऐसे `data-` के भीतर रखे मान पर लागू होती है जिसे बाद में चलाया जाता है। इनमें से हर जगह का अपना escape है, और सही सवाल कभी «क्या यह escape हुआ है?» नहीं होता बल्कि «क्या यह उस जगह के लिए escape हुआ है जहाँ यह पहुँचता है?» होता है। यह औज़ार HTML वाली हालत का जवाब देता है।

DPDP Act के लिहाज़ से इसका क्या मतलब है

इस खाने में आम तौर पर किसी और का लिखा टेक्स्ट चिपकता है: किसी उपयोक्ता की टिप्पणी, कोई सपोर्ट संदेश, नामों वाला कोई विवरण। चूँकि प्रतिस्थापन पन्ने पर ही होता है, वह सामग्री हम तक नहीं पहुँचती और उस पर हमारी कोई प्रोसेसिंग की भूमिका नहीं बनती।

यह ब्राउज़र के नेटवर्क पैनल में जाँचा जा सकता है: इस्तेमाल के दौरान आपके इनपुट के साथ कोई रिक्वेस्ट नहीं निकलती। पन्ना CDN से आता है और साइट पर विज्ञापन हैं, इसलिए रिक्वेस्ट होती हैं — वे यह जानती हैं कि आप यहाँ थे, यह नहीं कि खाने में क्या है।

HTML encode करें: आम सवाल

क्या मेरा टेक्स्ट किसी सर्वर पर भेजा जाता है?

नहीं। प्रतिस्थापन इसी पन्ने पर, आपके ब्राउज़र में होता है। लिखते हुए नेटवर्क पैनल खोलिए और देखिए कि आपके इनपुट के साथ कोई रिक्वेस्ट नहीं निकलती।

मेरे हिंदी अक्षर escape क्यों नहीं होते?

क्योंकि HTML के parser के लिए वे सामान्य अक्षर हैं और UTF-8 दस्तावेज़ में वे कुछ नहीं तोड़ते। अगर आपकी प्रक्रिया-शृंखला UTF-8 नहीं सँभालती, तो दूसरी सेटिंग चुनिए और वे अंकों वाले संदर्भ बन जाएँगे।

क्या यह XSS से बचाता है?

जहाँ HTML बनाया जा रहा है, वहाँ हाँ: यही इसका काम है। यह इनपुट की जाँच की जगह नहीं लेता और उन मानों के लिए नहीं चलता जो JavaScript में, किसी href में या CSS के संदर्भ में पहुँचते हैं, जहाँ दूसरे नियम हैं।

नतीजे में मुझे `&amp;lt;` क्यों दिख रहा है?

क्योंकि टेक्स्ट पहले से escape होकर आया था और दोबारा escape हो गया। यह औज़ार की ख़राबी नहीं है: यह बताता है कि आपकी शृंखला में पहले ही कोई escape-सुविधा चल चुकी है, आम तौर पर आपके template इंजन की।

क्या लंबाई की कोई सीमा है?

सिर्फ़ वह जो आपका अपना ब्राउज़र लगाए। कोई सर्वर नहीं है जो कुछ गिने या सीमित करे; बहुत बड़े इनपुट पर टैब एक पल सोचता है, और बस इतना ही।

और टूल्स