XML-RPCバックエンドと通信するJavascriptコードがいくつかあります。 XML-RPCは次の形式の文字列を返します。
<img src='myimage.jpg'>
ただし、Javascriptを使用して文字列をHTMLに挿入すると、文字どおりにレンダリングされます。画像が表示されず、文字列が文字通り表示されます。
<img src='myimage.jpg'>
私の推測では、HTMLはXML-RPCチャネルを介してエスケープされています。
Javascriptで文字列をエスケープ解除するにはどうすればよいですか?このページのテクニックを試してみましたが、失敗しました: http://paulschreiber.com/blog/2008/09/20/javascript-how-to-unescape-html-entities/
問題を診断する他の方法は何ですか?
EDIT:DOMParser APIを Wladimirが示唆する として使用する必要があります。投稿された関数にセキュリティ脆弱性が導入されたため、以前の回答を編集しました。
次のスニペットは、小さな修正を加えた古い回答のコードです。textarea
の代わりにdiv
を使用すると、XSSの脆弱性が軽減されますが、IE9およびFirefoxでは依然として問題があります。
function htmlDecode(input){
var e = document.createElement('textarea');
e.innerHTML = input;
// handle case of empty input
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
htmlDecode("<img src='myimage.jpg'>");
// returns "<img src='myimage.jpg'>"
基本的に、プログラムでDOM要素を作成し、エンコードされたHTMLをそのinnerHTMLに割り当て、innerHTML挿入で作成されたテキストノードからnodeValueを取得します。要素を作成するだけで追加はしないため、サイトのHTMLは変更されません。
クロスブラウザ(古いブラウザを含む)で動作し、すべての HTML文字エンティティ を受け入れます。
編集:このコードの古いバージョンは、 ここではjsFiddleで (IEで表示)のように、空白の入力があるIEでは動作しませんでした。上記のバージョンはすべての入力で機能します。
更新:これは大きな文字列では機能せず、セキュリティ脆弱性も導入しています。コメントを参照してください。
ここで与えられるほとんどの答えには大きな欠点があります:変換しようとしている文字列が信頼されていない場合、 クロスサイトスクリプティング(XSS)の脆弱性 になります。 accepted answer の関数については、次のことを考慮してください。
htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");
ここの文字列にはエスケープされていないHTMLタグが含まれているため、何もデコードする代わりに、htmlDecode
関数は実際に文字列内で指定されたJavaScriptコードを実行します。
これは DOMParser を使用することで回避できます。これは すべての最新ブラウザー でサポートされています:
function htmlDecode(input)
{
var doc = new DOMParser().parseFromString(input, "text/html");
return doc.documentElement.textContent;
}
// This returns "<img src='myimage.jpg'>"
htmlDecode("<img src='myimage.jpg'>");
// This returns ""
htmlDecode("<img src='dummy' onerror='alert(/xss/)'>");
この関数は、副作用としてJavaScriptコードを実行しないことが保証されています。 HTMLタグは無視され、テキストコンテンツのみが返されます。
互換性メモ:DOMParser
を使用したHTMLの解析には、少なくともChrome 30、Firefox 12、Operaが必要です_ 17、Internet Explorer 10、Safari 7.1またはMicrosoft Edge。そのため、サポートされていないすべてのブラウザーはEOLを過ぎており、2017年の時点でまだ世間に見られる唯一のブラウザーは、古いInternet ExplorerとSafariバージョンだけです(通常、これらはまだ気にするほど多くありません)。
JQueryを使用している場合:
function htmlDecode(value){
return $('<div/>').html(value).text();
}
それ以外の場合は、 Strictly Software's Encoder Object を使用します。これには優れたhtmlDecode()
関数があります。
トリックは、ブラウザのパワーを使用して特別なHTML文字をデコードすることですが、ブラウザが実際のhtmlであるかのように結果を実行することを許可しません...一度に。
function unescapeHtml(html) {
var el = document.createElement('div');
return html.replace(/\&[#0-9a-z]+;/gi, function (enc) {
el.innerHTML = enc;
return el.innerText
});
}
エスケープを解除したいHTMLが65536文字よりも長くない限り、CMSの答えは問題なく機能します。 Chromeでは、内側のHTMLが多くて65536の子ノードに分割され、それらを連結する必要があるためです。この関数は、非常に長い文字列でも機能します。
function unencodeHtmlContent(escapedHtml) {
var elem = document.createElement('div');
elem.innerHTML = escapedHtml;
var result = '';
// Chrome splits innerHTML into many child nodes, each one at most 65536.
// Whereas FF creates just one single huge child node.
for (var i = 0; i < elem.childNodes.length; ++i) {
result = result + elem.childNodes[i].nodeValue;
}
return result;
}
詳細については、innerHTML
max lengthについてのこの回答を参照してください。 https://stackoverflow.com/a/27545633/694469
クリスの答えはナイスでエレガントですが、値がndefinedの場合は失敗します。単純な改善だけで確実になります:
function htmlDecode(value) {
return (typeof value === 'undefined') ? '' : $('<div/>').html(value).text();
}
あなたの質問への直接的な回答ではありませんが、RPCがその構造内の画像データ(例ではURL)を含む構造(XMLやJSONなど)を返す方が良いと思いませんか?
次に、javascriptで解析し、javascript自体を使用して<img>
をビルドします。
RPCから受け取る構造は次のようになります。
{"img" : ["myimage.jpg", "myimage2.jpg"]}
外部ソースからのコードをページに挿入することはあまり安全ではないため、この方法の方が良いと思います。誰かがあなたのXML-RPCスクリプトをハイジャックし、あなたがそこに望まない何かを置くことを画像化します(いくつかのjavascriptさえ...)
どういたしまして...メッセンジャーだけで...全額クレジットはourcodeworld.comにリンクされています。
window.htmlentities = {
/**
* Converts a string to its html characters completely.
*
* @param {String} str String with unescaped HTML characters
**/
encode : function(str) {
var buf = [];
for (var i=str.length-1;i>=0;i--) {
buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
}
return buf.join('');
},
/**
* Converts an html characterSet into its original character.
*
* @param {String} str htmlSet entities
**/
decode : function(str) {
return str.replace(/&#(\d+);/g, function(match, dec) {
return String.fromCharCode(dec);
});
}
};
完全なクレジット: https://ourcodeworld.com/articles/read/188/encode-and-decode-html-entities-using-pure-javascript
これは良いです:
String::decode = ->
$('<textarea />').html(this).text()
つかいます:
"<img src='myimage.jpg'>".decode();
from: HTMLエンティティデコード
ここにある他のすべての答えには問題があります。
Document.createElement( 'div')メソッド(jQueryを使用するメソッドを含む)は、渡されたJavaScript(セキュリティの問題)を実行し、DOMParser.parseFromString()メソッドは空白を削除します。どちらも問題のない純粋なJavaScriptソリューションを次に示します。
function htmlDecode(html) {
var textarea = document.createElement("textarea");
html= html.replace(/\r/g, String.fromCharCode(0xe000)); // Replace "\r" with reserved unicode character.
textarea.innerHTML = html;
var result = textarea.value;
return result.replace(new RegExp(String.fromCharCode(0xe000), 'g'), '\r');
}
TextAreaは、executig jsコードを回避するために特に使用されます。これらに合格します:
htmlDecode('<& >'); // returns "<& >" with non-breaking space.
htmlDecode(' '); // returns " "
htmlDecode('<img src="dummy" onerror="alert(\'xss\')">'); // Does not execute alert()
htmlDecode('\r\n') // returns "\r\n", doesn't lose the \r like other solutions.
私はこれを私のプロジェクトで使用します: その他の回答 に触発されましたが、追加の安全なパラメーターを使用すると、装飾された文字を扱うときに役立ちます
var decodeEntities=(function(){
var el=document.createElement('div');
return function(str, safeEscape){
if(str && typeof str === 'string'){
str=str.replace(/\</g, '<');
el.innerHTML=str;
if(el.innerText){
str=el.innerText;
el.innerText='';
}
else if(el.textContent){
str=el.textContent;
el.textContent='';
}
if(safeEscape)
str=str.replace(/\</g, '<');
}
return str;
}
})();
そして、それは次のように使用できます:
var label='safe <b> character éntity</b>';
var safehtml='<div title="'+decodeEntities(label)+'">'+decodeEntities(label, true)+'</div>';