HTML संस्थाओं के रूप में HTML टैग से बचने का सबसे तेज़ तरीका?


98

मैं एक Chrome एक्सटेंशन है एक कर शामिल है लिख रहा हूँ बहुत कुछ तार कि प्रतिबंध लगाया: निम्नलिखित काम का हो सकता है HTML टैग होते हैं, परिवर्तित करके <, >और &करने के लिए &lt;, &gt;और &amp;क्रमश:।

(दूसरे शब्दों में, PHP के समान ही htmlspecialchars(str, ENT_NOQUOTES)- मुझे नहीं लगता कि दोहरे-उद्धरण वर्णों को परिवर्तित करने की कोई वास्तविक आवश्यकता है।)

यह मेरे द्वारा अब तक पाया गया सबसे तेज़ कार्य है:

function safe_tags(str) {
    return str.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;') ;
}

लेकिन अभी भी एक बड़ा अंतराल है जब मुझे एक बार में इसके माध्यम से कुछ हज़ार तार चलाने होंगे।

क्या कोई इस पर सुधार कर सकता है? यह ज्यादातर 10 और 150 वर्णों के बीच तार के लिए है, अगर इससे कोई फर्क पड़ता है।

(एक विचार जो मुझे अधिक से अधिक सांकेतिक शब्दों में बदलना परेशान करने के लिए नहीं था - क्या इसके साथ कोई वास्तविक खतरा होगा?)


2
क्यों? अधिकांश मामलों में जो आप ऐसा करना चाहते हैं, आप डेटा को DOM में सम्मिलित करना चाहते हैं, उस स्थिति में आपको इसे बच निकलने के बारे में भूल जाना चाहिए और बस इससे एक TextNode करना चाहिए।
क्वेंटिन

1
@ डेविड डोरवर्ड: शायद वह POST डेटा को सुरक्षित करना चाहते थे, और सर्वर डेटा को सही तरीके से राउंड-ट्रिप नहीं करता है।
रेयान

4
@ लाइ - अगर ऐसा है, तो समाधान है "पीट की खातिर, सर्वर को ठीक करें क्योंकि आपके पास एक बड़ा XSS छेद है"
क्वेंटिन

2
@ डेविड डोरवर्ड: यह संभव है कि मामला यह है कि सर्वर पर उसका नियंत्रण नहीं है। मैं हाल ही में ऐसी स्थिति में आया हूं, जहां मैं अपने विश्वविद्यालय की वेबसाइट में पसंद न आने वाली चीजों को एक-एक करके लिखने के लिए एक ग्रिसेमनी स्क्रिप्ट लिख रहा था; मुझे एक सर्वर पर एक POST करना था जिसका मेरे पास जावास्क्रिप्ट का उपयोग करके POST डेटा को नियंत्रित करने और उसे पवित्र करने के लिए नहीं है (क्योंकि कच्चा डेटा एक अमीर टेक्स्टबॉक्स से आता है, और इसलिए html टैग्स के ढेर हैं जो सर्वर पर राउंड ट्रिप नहीं करता है) । वेब व्यवस्थापक वेबसाइट को ठीक करने के लिए मेरे अनुरोध को अनदेखा कर रहा था, इसलिए मेरे पास कोई अन्य विकल्प नहीं था।
रेयान

1
मेरे पास एक उपयोग-मामला है जहां मुझे एक div में एक त्रुटि संदेश प्रदर्शित करने की आवश्यकता है। त्रुटि संदेश में HTML और newlines हो सकते हैं। मैं HTML से बचना चाहता हूं और <br> के साथ नईलाइन्स को बदलना चाहता हूं। फिर परिणाम को प्रदर्शन के लिए एक div में रखें।
mozey

जवाबों:


83

आप प्रतिस्थापन करने के लिए कॉलबैक फ़ंक्शन पास करने का प्रयास कर सकते हैं:

var tagsToReplace = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;'
};

function replaceTag(tag) {
    return tagsToReplace[tag] || tag;
}

function safe_tags_replace(str) {
    return str.replace(/[&<>]/g, replaceTag);
}

यहाँ एक प्रदर्शन परीक्षण है: http://jsperf.com/encode-html-entitiesreplace फ़ंक्शन को बार-बार कॉल करने के साथ तुलना करने के लिए और डोम द्वारा प्रस्तावित डोम विधि का उपयोग करने के लिए।

आपका रास्ता तेज़ हो रहा है ...

आपको इसकी आवश्यकता क्यों है, यद्यपि?


2
भागने की कोई जरूरत नहीं है >

6
वास्तव में यदि आप एक html तत्व की विशेषता में बच गए मूल्य को डालते हैं, तो आपको> प्रतीक से बचने की आवश्यकता है। अन्यथा यह उस HTML तत्व के लिए टैग को तोड़ देगा।
ज़्लतिन ज़्लाटेव

1
सामान्य पाठ में भागे हुए अक्षर दुर्लभ हैं। जरूरत पड़ने पर ही कॉल को रिप्लेस करना बेहतर होता है, अगर आप अधिकतम स्पीड की परवाह करते हैं:if (/[<>&"]/.test(str) { ... }
विटली

3
@callum: नहीं। मुझे उन मामलों की गणना करने में कोई दिलचस्पी नहीं है जिनमें मुझे लगता है कि "कुछ गलत हो सकता है" (कम से कम क्योंकि यह अप्रत्याशित / भूल गए मामले हैं जो आपको चोट पहुंचाएंगे, और जब आप कम से कम उस पर उम्मीद करेंगे)। मैं मानकों को कोडित करने में दिलचस्पी रखता हूं (इसलिए अप्रत्याशित / भूल गए मामले आपको परिभाषा से चोट नहीं पहुंचा सकते हैं )। मैं यह नहीं कह सकता कि यह कितना महत्वपूर्ण है। >HTML में एक विशेष चरित्र है, इसलिए इसे छोड़ दें। इतना ही आसान। :)
ऑर्बिट

4
@LightnessRacesinOrbit यह प्रासंगिक है क्योंकि सवाल यह है कि सबसे तेज़ संभव तरीका क्या है। यदि >प्रतिस्थापन को छोड़ना संभव है , तो यह तेजी से कर देगा।
कॉलम

104

यहाँ एक तरह से आप यह कर सकते हैं:

var escape = document.createElement('textarea');
function escapeHTML(html) {
    escape.textContent = html;
    return escape.innerHTML;
}

function unescapeHTML(html) {
    escape.innerHTML = html;
    return escape.textContent;
}

यहाँ एक डेमो है।


डेमो को फिर से डिजाइन किया। यहाँ एक फुलस्क्रीन संस्करण है: jsfiddle.net/Daniel_Hug/qPUEX/show/light
Web_Designer

13
निश्चित नहीं है कि कैसे / क्या / क्यों - लेकिन यह प्रतिभा है।
रोब_जम्स

4
ऐसा लगता है कि यह शाब्दिक पाठ से बचने के लिए TextArea तत्व के मौजूदा कोड का लाभ उठा रहा है। बहुत अच्छा, मुझे लगता है कि यह छोटी सी चाल एक और घर खोजने जा रही है।
अजाक्स

3
@ जजकट मैं उस फंक्शन का उपयोग नहीं कर रहा हूं। मेरे द्वारा उपयोग किया जाने वाला एस्केप वैरिएबल, मैं खुद को उदाहरण में परिभाषित करता हूं।
Web_Designer

2
लेकिन क्या इससे व्हाइट स्पेस वगैरह खो जाता है
एंड्रयू

31

प्रोटोटाइप फ़ंक्शन के रूप में मार्टिज़न की विधि:

String.prototype.escape = function() {
    var tagsToReplace = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;'
    };
    return this.replace(/[&<>]/g, function(tag) {
        return tagsToReplace[tag] || tag;
    });
};

var a = "<abc>";
var b = a.escape(); // "&lt;abc&gt;"

12
Stringयह इस तरह से जोड़ना चाहिए क्योंकि यह सामान्य रूप से एक स्ट्रिंग के लिए एक भागने नहीं है, क्योंकि यह Html होना चाहिए । यह String.escapeHtmlसही है, लेकिन String.escapeसवाल उठाता है, "किस लिए पलायन?"
लॉरेंस Dol

3
हाँ अच्छा विचार है। मैं संघर्षों से बचने के लिए इन दिनों प्रोटोटाइप का विस्तार करने से दूर हो गया हूं।
अराम कोचरन

1
यदि आपके ब्राउज़र में Symbol का समर्थन है, तो आप स्ट्रिंग-कुंजी नामस्थान को प्रदूषित करने से बचने के लिए इसका उपयोग कर सकते हैं। var भागने = नया प्रतीक ("बच"); String.prototype [बच] = फ़ंक्शन () {...}; "पाठ" [भागने] ();
अजाक्स

12

एक भी तेज / कम समाधान है:

escaped = new Option(html).innerHTML

यह जावास्क्रिप्ट के कुछ अजीब दायरे से संबंधित है जिससे विकल्प तत्व एक ऐसे निर्माता को बनाए रखता है जो इस प्रकार का स्वचालित रूप से बच निकलता है।

इसका श्रेय https://github.com/jasonmoo/t.js/blob/master/t.js को दिया जाता है


1
नीट वन-लाइनर लेकिन रेगेक्स के बाद सबसे धीमी विधि । इसके अलावा, पाठ में व्हाट्सएप छीन लिया जा सकता है, कल्पना के
शॉर्टफ्यूज

ध्यान दें कि @ ShortFuse का "सबसे धीमा तरीका" लिंक मेरे सिस्टम को RAM से बाहर चलाता है (~ 6 जीबी मुफ्त के साथ) और फ़ायरफ़ॉक्स को स्मृति से बाहर होने से ठीक पहले आवंटित करना बंद करना प्रतीत होता है इसलिए आपत्तिजनक प्रक्रिया को मारने के बजाय, लिनक्स वहां बैठ जाएगा और आपको करने देगा एक कठिन शक्ति बंद।
ल्यूक

11

AngularJS स्रोत कोड में कोणीय-सैनिटाइज़.जेएस के अंदर एक संस्करण भी है ।

var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
    // Match everything outside of normal chars and " (quote character)
    NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
/**
 * Escapes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} escaped text
 */
function encodeEntities(value) {
  return value.
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, function(value) {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, function(value) {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

1
वाह, वह गैर-अल्फानूम रेगेक्स तीव्र है। मुझे नहीं लगता | हालांकि अभिव्यक्ति की जरूरत है।
अजाक्स

11

सबसे तेज़ विधि है:

function escapeHTML(html) {
    return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
}

यह विधि 'बदलें' पर आधारित विधियों की तुलना में लगभग दोगुनी तेज़ है, http://jsperf.com/htmlencoderegex/35 देखें ।

स्रोत: https://stackoverflow.com/a/17546215/698168


9

ऑल-इन-वन स्क्रिप्ट:

// HTML entities Encode/Decode

function htmlspecialchars(str) {
    var map = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        "\"": "&quot;",
        "'": "&#39;" // ' -> &apos; for XML only
    };
    return str.replace(/[&<>"']/g, function(m) { return map[m]; });
}
function htmlspecialchars_decode(str) {
    var map = {
        "&amp;": "&",
        "&lt;": "<",
        "&gt;": ">",
        "&quot;": "\"",
        "&#39;": "'"
    };
    return str.replace(/(&amp;|&lt;|&gt;|&quot;|&#39;)/g, function(m) { return map[m]; });
}
function htmlentities(str) {
    var textarea = document.createElement("textarea");
    textarea.innerHTML = str;
    return textarea.innerHTML;
}
function htmlentities_decode(str) {
    var textarea = document.createElement("textarea");
    textarea.innerHTML = str;
    return textarea.value;
}

http://pastebin.com/JGCVs0Ts


मैं नीचे नहीं गया, लेकिन सभी रेगेक्स शैली की जगह यूनिकोड को एनकोड करने में विफल रहेगी ... इसलिए, किसी भी विदेशी भाषा का उपयोग करने वाला निराश होने वाला है। ऊपर उल्लिखित <textarea> ट्रिक वास्तव में शांत है और जल्दी और सुरक्षित रूप से सब कुछ संभालती है।
अजाक्स

रेगेक्स मेरे लिए कई गैर-लैटिन यूनिकोड वर्णों के साथ ठीक काम करता है। मुझे कुछ और उम्मीद नहीं होगी। आपको कैसे लगता है कि यह काम नहीं करेगा? क्या आप एकल-बाइट कोडप्स के बारे में सोच रहे हैं जिनके लिए HTML संस्थाओं की आवश्यकता है? यही कारण है कि तीसरे और चौथे समारोह के लिए हैं, और स्पष्ट रूप से 1 और दूसरा नहीं है। मुझे भेदभाव पसंद है।
17

@ LonelyPixel मुझे नहीं लगता कि वह आपकी टिप्पणी को देखेगा यदि आप उसका उल्लेख नहीं करते हैं ("केवल एक अतिरिक्त उपयोगकर्ता को सूचित किया जा सकता है; पोस्ट मालिक को हमेशा सूचित किया जाएगा")
baptx

मुझे पता नहीं था कि लक्षित सूचनाएं बिल्कुल मौजूद हैं। @ अजाक्स कृपया मेरी टिप्पणी ऊपर देखें।
योगो

@LonelyPixel अब मैं देख रहा हूं। किसी कारण से मुझे नहीं लगा कि इस उत्तर में कोई टेक्स्टएयर शैली प्रतिस्थापन है। मैं, मैंडरिन की तरह डबल कोडपॉइंट बड़े यूनिकोड मूल्यों के बारे में सोच रहा था। मेरा मतलब है, एक रेगेक्स को काफी स्मार्ट बनाना संभव होगा, लेकिन जब आप ब्राउज़र विक्रेताओं द्वारा लिए जा सकने वाले शॉर्टकट्स को देखते हैं, तो मैं बहुत अच्छा सट्टेबाजी महसूस करूंगा कि टेक्स्टारिया बहुत तेजी से (पूरी तरह से सक्षम रेगेक्स की तुलना में) होगा। क्या किसी ने इस जवाब पर एक बेंचमार्क पोस्ट किया? मैंने कसम खाई थी कि मैंने एक को देखा था।
अजाक्स

2

function encode(r) {
  return r.replace(/[\x26\x0A\x3c\x3e\x22\x27]/g, function(r) {
	return "&#" + r.charCodeAt(0) + ";";
  });
}

test.value=encode('How to encode\nonly html tags &<>\'" nice & fast!');

/*
 \x26 is &ampersand (it has to be first),
 \x0A is newline,
 \x22 is ",
 \x27 is ',
 \x3c is <,
 \x3e is >
*/
<textarea id=test rows=11 cols=55>www.WHAK.com</textarea>


1

मैं पूरी तरह से गति के बारे में निश्चित नहीं हूं, लेकिन अगर आप सादगी की तलाश में हैं तो मैं लॉश / अंडरस्कोर एस्केप फ़ंक्शन का उपयोग करने का सुझाव दूंगा ।


0

" चिह्न ( जावास्क्रिप्ट में उपयोग ) को संभालने के साथ एकल फ़ंक्शन के रूप में मार्टिज़न की विधि :

function escapeHTML(html) {
    var fn=function(tag) {
        var charsToReplace = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&#34;'
        };
        return charsToReplace[tag] || tag;
    }
    return html.replace(/[&<>"]/g, fn);
}

0

मैं XMLSerializerढेर में जोड़ दूँगा । यह किसी भी वस्तु कैशिंग (क्रमिक पर न तो पाठ नोड पर) का उपयोग किए बिना सबसे तेज़ परिणाम प्रदान करता है।

function serializeTextNode(text) {
  return new XMLSerializer().serializeToString(document.createTextNode(text));
}

जोड़ा बोनस यह है कि यह उन विशेषताओं का समर्थन करता है जो पाठ नोड्स की तुलना में अलग-अलग क्रमबद्ध हैं:

function serializeAttributeValue(value) {
  const attr = document.createAttribute('a');
  attr.value = value;
  return new XMLSerializer().serializeToString(attr);
}

आप यह देख सकते हैं कि यह वास्तव में क्या है, पाठ नोड्स के लिए और विशेषता मानों के लिए कल्पना की जाँच करके । पूर्ण प्रलेखन में अधिक नोड प्रकार हैं, लेकिन अवधारणा समान है।

प्रदर्शन के लिए, यह सबसे तेज़ है जब कैश नहीं किया जाता है। जब आप कैशिंग की अनुमति देते हैं, तो innerHTMLबच्चे के टेक्स्ट नोड के साथ HTMLElement पर कॉल करना सबसे तेज़ है। रेगेक्स सबसे धीमा होगा (जैसा कि अन्य टिप्पणियों से साबित होता है)। बेशक, XMLSerializer अन्य ब्राउज़रों पर तेज़ हो सकता है, लेकिन मेरे (सीमित) परीक्षण में, innerHTMLसबसे तेज़ है।


सबसे तेज सिंगल लाइन:

new XMLSerializer().serializeToString(document.createTextNode(text));

कैशिंग के साथ सबसे तेज़:

const cachedElementParent = document.createElement('div');
const cachedChildTextNode = document.createTextNode('');
cachedElementParent.appendChild(cachedChildTextNode);

function serializeTextNode(text) {
  cachedChildTextNode.nodeValue = text;
  return cachedElementParent.innerHTML;
}

https://jsperf.com/htmlentityencode/1


-3

एक शो के लिए देर से काटा, लेकिन क्या उपयोग करने के साथ गलत क्या है encodeURIComponent () और decodeURIComponent () ?


1
वे पूरी तरह से असंबंधित कुछ करते हैं
कॉल

1
शायद "पूरी तरह से" शब्द का सबसे बड़ा दुरुपयोग मैंने कभी सुना है। उदाहरण के लिए, मुख्य विषय के प्रश्न के संबंध में, इसका उपयोग html स्ट्रिंग को डिकोड करने के लिए किया जा सकता है (जाहिर है कुछ थोड़े भंडारण कारण के लिए), html टैग्स की परवाह किए बिना, और फिर आवश्यकता पड़ने पर इसे फिर से पुनः html में एनकोड कर सकते हैं।
suncat100
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.