डिकोड & amp; वापस जावास्क्रिप्ट में


229

मेरे पास तार हैं

var str = 'One & two & three';

वेब सर्वर द्वारा HTML में प्रदान किया गया। मुझे उन तारों को बदलने की जरूरत है

'One & two & three'

वर्तमान में, मैं यही कर रहा हूं (jQuery की मदद से):

$(document.createElement('div')).html('{{ driver.person.name }}').text()

हालाँकि मुझे इस बात का अहसास है कि मैं इसे गलत कर रहा हूँ। मैंने कोशिश की है

unescape("&")

लेकिन यह काम करने के लिए प्रतीत नहीं होता है, न ही डिकोड्यूरी / डिकोड्यूरिकॉमपेंट नहीं है।

क्या ऐसा करने के कोई अन्य, अधिक देशी और सुरुचिपूर्ण तरीके हैं?


इस लेख में शामिल विशाल फ़ंक्शन ठीक काम करता है: blogs.msdn.com/b/aoakley/archive/2003/11/12/49645.aspx मुझे नहीं लगता कि यह सबसे चतुर समाधान है, लेकिन काम करता है।
मत्तीस

1
जैसे कि HTML निकाय वाले स्ट्रिंग्स escaped या URI एन्कोडेड स्ट्रिंग्स की तुलना में कुछ अलग होते हैं , वे फ़ंक्शन काम नहीं करेंगे।
मार्सेल कोर्पेल

1
@Matias ध्यान दें कि नई नामित संस्थाओं को HTML में जोड़ा गया है (जैसे HTML 5 कल्पना के माध्यम से) क्योंकि उस फ़ंक्शन को 2003 में लिखा गया था - उदाहरण के लिए, यह पहचान नहीं करता है 𝕫। यह एक उभरती हुई युक्ति के साथ एक समस्या है; जैसे, आपको एक उपकरण चुनना चाहिए जिसे वास्तव में इसे हल करने के लिए बनाए रखा जा रहा है।
मार्क अमेरी

1
@ मार्की हाँ, मैं पूरी तरह से सहमत हूँ! यह कुछ वर्षों के बाद इस सवाल पर वापस आने के लिए एक अच्छा अनुभव है, धन्यवाद!
मटीस

जवाबों:


104

जावास्क्रिप्ट से HTML (पाठ और अन्यथा) की व्याख्या करने के लिए एक और आधुनिक विकल्प DOMParserएपीआई में HTML समर्थन है ( एमडीएन में यहां देखें )। यह आपको ब्राउज़र के मूल HTML पार्सर का उपयोग करके स्ट्रिंग को HTML दस्तावेज़ में बदलने की अनुमति देता है। 2014 के अंत से सभी प्रमुख ब्राउज़रों के नए संस्करणों में इसका समर्थन किया गया है।

यदि हम केवल कुछ पाठ्य सामग्री को डीकोड करना चाहते हैं, तो हम इसे एक डॉक्यूमेंट बॉडी में एकमात्र कंटेंट के रूप में रख सकते हैं, डॉक्यूमेंट को पार्स कर सकते हैं, और इसके बाहर खींच सकते हैं .body.textContent

var encodedStr = 'hello & world';

var parser = new DOMParser;
var dom = parser.parseFromString(
    '<!doctype html><body>' + encodedStr,
    'text/html');
var decodedString = dom.body.textContent;

console.log(decodedString);

हम ड्राफ्ट विनिर्देशDOMParser में देख सकते हैं कि जावास्क्रिप्ट को पार्स किए गए दस्तावेज़ के लिए सक्षम नहीं किया गया है, इसलिए हम सुरक्षा चिंताओं के बिना इस पाठ रूपांतरण का प्रदर्शन कर सकते हैं।

इस प्रकार केparseFromString(str, type) आधार पर विधि को ये चरण चलाने चाहिए :

  • "text/html"

    पार्स str एक साथ HTML parser, और नव निर्मित लौटने Document

    स्क्रिप्टिंग ध्वज को "अक्षम" पर सेट किया जाना चाहिए।

    ध्यान दें

    scriptतत्वों को अप्राप्य के रूप में चिह्नित noscriptकिया जाता है और मार्कअप के रूप में प्राप्त की गई सामग्री ।

यह इस प्रश्न के दायरे से परे है, लेकिन कृपया ध्यान दें कि यदि आप पार्स किए गए डोम नोड्स को ले रहे हैं (न कि केवल उनकी पाठ सामग्री) और उन्हें लाइव दस्तावेज़ डोम में ले जा रहे हैं, तो संभव है कि उनकी स्क्रिप्टिंग फिर से सक्षम हो जाए, और वहां हो सकता है सुरक्षा की चिंता करें। मैंने इस पर शोध नहीं किया है, इसलिए कृपया सावधानी बरतें।


5
NodeJs के लिए कोई विकल्प?
कोडरइरैन

284

क्या आपको सभी एन्कोडेड HTML संस्थाओं या केवल &amp;स्वयं को डीकोड करने की आवश्यकता है?

यदि आपको केवल संभालने की आवश्यकता है &amp;तो आप यह कर सकते हैं:

var decoded = encoded.replace(/&amp;/g, '&');

यदि आपको सभी HTML संस्थाओं को डीकोड करने की आवश्यकता है तो आप इसे jQuery के बिना कर सकते हैं:

var elem = document.createElement('textarea');
elem.innerHTML = encoded;
var decoded = elem.value;

कृपया नीचे दिए गए मार्क की टिप्पणियों पर ध्यान दें, जो इस उत्तर के पुराने संस्करण में सुरक्षा छेद को उजागर करते हैं और संभावित XX कमजोरियों के खिलाफ कम करने के textareaबजाय उपयोग करने की सलाह देते हैं div। ये कमजोरियाँ मौजूद हैं चाहे आप jQuery का उपयोग करें या सादे जावास्क्रिप्ट का।


16
सावधान रहें! यह संभावित असुरक्षित है। अगर encoded='<img src="bla" onerror="alert(1)">'इसके बाद ऊपर का स्निपेट अलर्ट दिखाएगा। इसका मतलब है कि यदि आपका एन्कोडेड पाठ उपयोगकर्ता इनपुट से आ रहा है, तो इस स्निपेट के साथ डिकोडिंग एक XSS भेद्यता प्रस्तुत कर सकता है।
मार्क अमेरी

@MarkAmery मैं कोई सुरक्षा विशेषज्ञ नहीं हूं, लेकिन ऐसा लगता है कि यदि आप nullपाठ प्राप्त करने के बाद तुरंत div सेट करते हैं , तो img में चेतावनी नहीं निकाल दी जाती है - jsfiddle.net/Mottie/gaBeb/128
Mottie

4
@ बहुत ध्यान दें कि आपके लिए किस ब्राउज़र ने काम किया है, लेकिन alert(1)अभी भी मेरे लिए क्रोम पर ओएस एक्स पर फायर किया जाता है। यदि आप इस हैक का एक सुरक्षित संस्करण चाहते हैं, तो एक का उपयोगtextarea करने का प्रयास करें
मार्क एमी जूल

साधारण रीजेक्सपी के लिए +1, केवल एक प्रकार की HTML इकाई के लिए विकल्प को प्रतिस्थापित करता है। यदि आप html डेटा से प्रक्षेपित होने की उम्मीद कर रहे हैं, तो इसका उपयोग करें, कहते हैं, एक टेम्पलेट के लिए अजगर फ्लास्क ऐप।
ओजीजीजेंट

नोड सर्वर पर यह कैसे करें?
मोहम्मद करमानी

44

माथियास ब्यानेन्स के पास इसके लिए एक पुस्तकालय है: https://github.com/mathiasbynens/he

उदाहरण:

console.log(
    he.decode("J&#246;rg &amp J&#xFC;rgen rocked to &amp; fro ")
);
// Logs "Jörg & Jürgen rocked to & fro"

मैं सुझाव देता हूं कि किसी तत्व की HTML सामग्री सेट करने और उसके पाठ सामग्री को वापस पढ़ने वाले हैक्स पर इसका समर्थन करें। इस तरह के दृष्टिकोण काम कर सकते हैं, लेकिन धोखे से खतरनाक और वर्तमान XSS अवसर हैं यदि अविश्वासित उपयोगकर्ता इनपुट पर उपयोग किया जाता है।

यदि आप वास्तव में एक पुस्तकालय में लोड करने के लिए सहन नहीं कर सकते हैं, तो आप इस उत्तरtextarea में वर्णित हैक का उपयोग लगभग डुप्लिकेट प्रश्न के लिए कर सकते हैं, जो कि सुझाए गए विभिन्न समान दृष्टिकोणों के विपरीत, कोई सुरक्षा छेद नहीं है जो मुझे पता है:

function decodeEntities(encodedString) {
    var textArea = document.createElement('textarea');
    textArea.innerHTML = encodedString;
    return textArea.value;
}

console.log(decodeEntities('1 &amp; 2')); // '1 & 2'

लेकिन इस एक के समान दृष्टिकोण को प्रभावित करने वाले सुरक्षा मुद्दों पर ध्यान दें, जो कि मैं जुड़े हुए उत्तर में सूचीबद्ध करता हूं! यह दृष्टिकोण एक हैक है, और भविष्य में textarea(या किसी विशेष ब्राउज़र में बग) की अनुमेय सामग्री में परिवर्तन होने से कोड हो सकता है जो एक दिन में अचानक XSS छेद होने पर निर्भर करता है।


मथायस ब्येनेंस की लाइब्रेरी heबिल्कुल शानदार है! सिफारिश के लिए बहुत-बहुत धन्यवाद!
पेड्रो ए

23
var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.push(echar);
            entityKeys.push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

यह एक्सटीजेएस स्रोत कोड से है।


4
-1; यह नामांकित संस्थाओं के विशाल बहुमत को संभालने में विफल रहता है। उदाहरण के लिए, htmlEnDecode.htmlDecode('&euro;')लौटना चाहिए '€', लेकिन बदले में '&euro;'
मार्क अमेरी


15

आप Lodash unescape / एस्केप फंक्शन https://lodash.com/docs/4.17.5#unescape का उपयोग कर सकते हैं

import unescape from 'lodash/unescape';

const str = unescape('fred, barney, &amp; pebbles');

str बन जाएगा 'fred, barney, & pebbles'


1
शायद "लॉश / अनस्केप 'से _unescape आयात करना बेहतर है?" इसलिए यह एक ही नाम के
हटाए

14

मामले में आप इसे पसंद कर रहे हैं, मेरी तरह - इस बीच एक अच्छा और सुरक्षित JQuery तरीका है।

https://api.jquery.com/jquery.parsehtml/

आप f.ex. इसे अपने कंसोल में लिखें:

var x = "test &amp;";
> undefined
$.parseHTML(x)[0].textContent
> "test &"

तो $ .parseHTML (x) एक सरणी देता है, और यदि आपके पास अपने पाठ के भीतर HTML मार्कअप है, तो array.length 1 से अधिक होगी।


मेरे लिए पूरी तरह से काम किया, यह वही था जो मैं देख रहा था, धन्यवाद।
जोनाथन नील्सन

1
यदि ऊपर xका मान <script>alert('hello');</script>दुर्घटनाग्रस्त हो जाएगा। वर्तमान jQuery में यह वास्तव में स्क्रिप्ट चलाने के लिए कोशिश नहीं करेंगे, लेकिन [0]निकलेगा undefinedताकि कॉल textContentविफल हो जाएगा और अपनी स्क्रिप्ट वहाँ बंद हो जाएगा। $('<div />').html(x).text();सुरक्षित दिखता है - gist.github.com/jmblog/3222899 के
एंड्रयू हॉजकिंसन

@AndrewHodgkinson हाँ, लेकिन सवाल था "जावास्क्रिप्ट में वापस & amp; डिकोड करें" - तो आप पहले x की सामग्री का परीक्षण करेंगे या सुनिश्चित करेंगे कि आप केवल सही मामलों में इसका उपयोग करते हैं।
सीएसलोटी

मैं वास्तव में नहीं देखता कि यह कैसे होता है। उपरोक्त कोड सभी मामलों में काम करता है। और बस कैसे ठीक से आप "सुनिश्चित करें" x के मूल्य को ठीक करने की आवश्यकता होगी? और क्या होगा यदि स्क्रिप्ट ऊपर दी गई चेतावनी '& amp;' ताकि यह वास्तव में सुधार की जरूरत है? हमें पता नहीं है कि ओपी के तार कहां से आते हैं, इसलिए दुर्भावनापूर्ण इनपुट पर विचार किया जाना चाहिए।
एंड्रयू होडकिंसन

@AndrewHodgkinson मुझे आपका विचार पसंद है, लेकिन यहाँ यह सवाल नहीं है। उस सवाल का जवाब देने के लिए स्वतंत्र महसूस करें, हालांकि। मुझे लगता है कि आप स्क्रिप्ट टैग निकाल सकते हैं, f.ex.
cslotty

8

jQuery आप के लिए सांकेतिक शब्दों में बदलना और डिकोड करेगा। हालांकि, आपको एक टेक्सैरिया टैग का उपयोग करने की आवश्यकता है, एक div नहीं।

var str1 = 'One & two & three';
var str2 = "One &amp; two &amp; three";
  
$(document).ready(function() {
   $("#encoded").text(htmlEncode(str1)); 
   $("#decoded").text(htmlDecode(str2));
});

function htmlDecode(value) {
  return $("<textarea/>").html(value).text();
}

function htmlEncode(value) {
  return $('<textarea/>').text(value).html();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<div id="encoded"></div>
<div id="decoded"></div>


2
-1 क्योंकि पुराने jQuery के संस्करणों के लिए यहां (आश्चर्यजनक) सुरक्षा छेद है, जिनमें से कुछ में अभी भी एक महत्वपूर्ण उपयोगकर्ता आधार है - उन संस्करणों का पता चलेगा और HTML में लिपियों का स्पष्ट रूप से मूल्यांकन किया जाएगा .html()। इस प्रकार यहां तक textareaकि सुरक्षा सुनिश्चित करने के लिए भी पर्याप्त नहीं है; मेरा सुझाव है कि इस कार्य के लिए jQuery का उपयोग न करें और सादे DOM API के साथ बराबर कोड लिखें । (हां, jQuery का वह पुराना व्यवहार पागल और भयानक है।)
मार्क अमेरी

उसे इंगित करने के लिए धन्यवाद। हालांकि, प्रश्न में स्क्रिप्ट इंजेक्शन की जांच करने की आवश्यकता शामिल नहीं है। प्रश्न विशेष रूप से वेब सर्वर द्वारा प्रदान किए गए html के बारे में पूछता है। किसी वेब सर्वर पर सेव की गई एचटीएमएल सामग्री को शायद स्क्रिप्ट से बचाने के लिए पहले मान्य किया जाना चाहिए।
जेसन विलियम्स

4

पहले <span id="decodeIt" style="display:none;"></span>शरीर में कहीं पैदा करो

इसके बाद, स्ट्रिंग को इनर HTML के रूप में डिकोड किया जाना है:

document.getElementById("decodeIt").innerHTML=stringtodecode

आखिरकार,

stringtodecode=document.getElementById("decodeIt").innerText

यहाँ समग्र कोड है:

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText

1
-1; यह अविश्वसनीय रूप से असुरक्षित इनपुट पर उपयोग करने के लिए असुरक्षित है। उदाहरण के लिए, विचार करें कि क्या होता है अगर stringtodecodeकुछ ऐसा है <script>alert(1)</script>
मार्क एमी

2

एक जावास्क्रिप्ट समाधान जो आम लोगों को पकड़ता है:

var map = {amp: '&', lt: '<', gt: '>', quot: '"', '#039': "'"}
str = str.replace(/&([^;]+);/g, (m, c) => map[c])

यह https://stackoverflow.com/a/4835406/2738039 का उल्टा है


यदि आप map[c] || ''गैर-मान्यता प्राप्त लोगों का उपयोग करते हैं, तो उन्हें दिखाया नहीं जाएगाundefined
एल्डेलशेल

बहुत सीमित कवरेज; -1।
मार्क अमेरी

2
+1, और अधिक हैunescapeHtml(str){ var map = {amp: '&', lt: '<', le: '≤', gt: '>', ge: '≥', quot: '"', '#039': "'"} return str.replace(/&([^;]+);/g, (m, c) => map[c]|| '') }
Trần Quốc Hoài new 2015

मैनुअल कवरेज। सिफारिश नहीं की गई।
सर्जियो ए।

2

एक-पंक्ति वाले लोगों के लिए:

const htmlDecode = innerHTML => Object.assign(document.createElement('textarea'), {innerHTML}).value;

console.log(htmlDecode('Complicated - Dimitri Vegas &amp; Like Mike'));

2

प्रश्न की उत्पत्ति निर्दिष्ट नहीं है, xलेकिन यह दुर्भावनापूर्ण (या हमारे स्वयं के अनुप्रयोग से) अनपेक्षित के खिलाफ, यदि हम कर सकते हैं, तो बचाव के लिए समझ में आता है। उदाहरण के लिए, मान लीजिए कि xमान है &amp; <script>alert('hello');</script>। JQuery में इसे संभालने का एक सुरक्षित और सरल तरीका है:

var x    = "&amp; <script>alert('hello');</script>";
var safe = $('<div />').html(x).text();

// => "& alert('hello');"

Https://gist.github.com/jmblog/3222899 के माध्यम से मिला । मैं इस समाधान का उपयोग करने से बचने के कई कारण नहीं देख सकता क्योंकि यह कम से कम है, अगर कुछ विकल्पों से कम नहीं है और XSS के खिलाफ रक्षा प्रदान करता है।

(मैंने मूल रूप से इसे एक टिप्पणी के रूप में पोस्ट किया था, लेकिन एक उत्तर के रूप में उसी धागे में एक बाद की टिप्पणी के बाद से यह अनुरोध कर रहा हूं कि मैं ऐसा करता हूं)।


1

मैंने JSON सरणी से निकालने और निकालने के लिए सब कुछ करने की कोशिश की। उपरोक्त उदाहरणों में से कोई भी नहीं, लेकिन https://stackoverflow.com/users/2030321/chris ने एक शानदार समाधान दिया जिससे मुझे अपनी समस्या ठीक करनी पड़ी।

var stringtodecode="<B>Hello</B> world<br>";
document.getElementById("decodeIt").innerHTML=stringtodecode;
stringtodecode=document.getElementById("decodeIt").innerText

मैंने उपयोग नहीं किया, क्योंकि मुझे समझ नहीं आया कि इसे एक मोडल विंडो में कैसे सम्मिलित किया जाए जो JSON डेटा को एक सरणी में खींच रहा है, लेकिन मैंने उदाहरण के आधार पर यह कोशिश की, और यह काम किया:

var modal = document.getElementById('demodal');
$('#ampersandcontent').text(replaceAll(data[0],"&amp;", "&"));

मुझे यह पसंद है क्योंकि यह सरल था, और यह काम करता है, लेकिन यह सुनिश्चित नहीं है कि इसका व्यापक रूप से उपयोग क्यों नहीं किया जाता है। एक सरल समाधान खोजने के लिए उच्च और निम्न खोजें। मैं वाक्यविन्यास की समझ हासिल करना जारी रखता हूं, और यदि इसका उपयोग करने के लिए कोई जोखिम है। अभी तक कुछ नहीं मिला।


आपका पहला प्रस्ताव थोड़ा मुश्किल है, लेकिन यह बहुत प्रयास के बिना अच्छा काम करता है। दूसरी ओर, वर्णों को डिकोड करने के लिए केवल ब्रूट बल का उपयोग करता है; इसका मतलब है कि यह पूर्ण डिकोडिंग फ़ंक्शन को पूरा करने के लिए बहुत प्रयास और समय ले सकता है। इसलिए ओपी की समस्या को हल करने के लिए कोई भी उस तरीके का उपयोग नहीं कर रहा है।
सर्जियो ए।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.