E4X Add CDATA content - actionscript-3

Basically I need to define a node name and its CDATA content using variables.
var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
Naively I thought this would work :
var xml:XML = <doc><{nodeName}><![CDATA[{nodeValue}]]></{nodeName}>
Outputs :
<doc><tag><![CDATA[{nodeValue}]]></tag></doc>
In a previous version of the script designed for FP9 I bypassed the problem by using :
new XMLNode( XMLNodeType.XMLNodeType.CDATA_NODE, nodeValue ); // ...
but this doesn't seem to work in FP10, and I have the feeling the method is somehow depreciated anyway.
Anyone an elegant solution for this ?

how about this:
var xml:XML = <doc><{nodeName}>{nodeValue}</{nodeName}></doc>
trace(xml.toXMLString());
outputs:
<doc>
<tag><non-escaped-content></tag>
</doc>
i admit, this is not CDATA, but i don't see a problem ... parsing requires a little more time, but OTOH, correct escaping much more robust than CDATA ...
the version with XMLNode uses the flash.xml package, which is for backwards compatibility with AS2 ... didn't even notice, it was gone under FP10 ... however, you could use this
var x:XML = new XML("<![CDATA[" + nodeValue + "]]>");
as a replacement and then use appendChild as you would with flash.xml ...
alternatively you could use it e4x style, if you wrap it in a function
function cdata(data:String):XML {
return = new XML("<![CDATA[" + data + "]]>");
}
and then
var xml:XML = <doc><{nodeName}>{cdata(nodeValue)}</{nodeName}></doc>
but personally, i think that strings, that are both text based and relatively short, should be escaped, rather then wrapped in CDATA ...
update:
i don't get your point here
"<" is very different than a "<"
that's what the whole thing is about ... :D ... "<" would be interpreted during parsing, whereas "<" is just reconverted to "<", so after parsing the XML, you will have exactly the same string as before ...
this is my code:
package {
import flash.display.MovieClip;
public class Main extends MovieClip {
public function Main():void {
var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><{nodeName}>{cdata(nodeValue)}</{nodeName}></doc>;
trace(cdata("test").toXMLString());
trace(xml.toXMLString());
}
private function cdata(data:String):XML {
return new XML("<![CDATA[" + data + "]]>");
}
}
}
works perfectly for me on flash player 10, compiled with flex sdk 4 ... don't have a flash IDE at hand, but when it comes to pure ActionScript results are almost definitely the same, so it should work (you can use that as your document class, if you want to, or simply instantiate it) ...
btw. the first trace shows, that the second example works, which is also quite obvious, since new XML(<String>) uses the native XML parser to create an XML from the given string ...
here is what the above generates:
<![CDATA[test]]>
<doc>
<tag><![CDATA[<non-escaped-content>]]></tag>
</doc>
works quite good for me ... :)
greetz
back2dos

The above cdata function needs to look like the following, notice the last ">" is escaped in code. Otherwise there's compile errors.
private function cdata(data:String):XML
{
return new XML("<![CDATA[" + data + "]]\>");
}

Thanks, cdata function is very useful. I wrote just new one.
function newNode(nodeName:String,nodeValue:String):XML{
return new XML(<{nodeName}>{cdata(nodeValue)}</{nodeName}>);
}

private function cdata(data:String, nodeName:String):XML{
return new XML( "<"+nodeName+"><![CDATA[" + data + "]]\></"+nodeName+">");
}
work fine :)

Here is another solution
public static function getCDATANode(data:String, tagName:String):void
{
var node:XML = new XML( "<" + tagName + "/>" );
var cdata:XML = new XML("<![CDATA[" + data + " ]]>");
node.appendChild(cdata);
trace("getCDATANode: ", node.toXMLString() );
}

Here's my solution without using functions:
var nodeName:String = "tag";
var nodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><{nodeName}>{new XML("<![CDATA[" + nodeValue + "]]>")}</{nodeName}></doc>;
If you need to replace existing nodes content and keep node attributes you can use:
var newNodeValue:String = "<non-escaped-content>";
var xml:XML = <doc><tag attribute="true">This is node content</tag></doc>;
xml.tag[0].setChildren(new XMLList());
xml.tag[0].appendChild(new XML("<![CDATA[" + newNodeValue + "]]>"));

Related

How to convert html5 characters like " " " in opentdb API to normal syntax using angular [duplicate]

This question already has answers here:
Unescape HTML entities in JavaScript?
(33 answers)
Closed 5 years ago.
Say I get some JSON back from a service request that looks like this:
{
"message": "We're unable to complete your request at this time."
}
I'm not sure why that apostraphe is encoded like that ('); all I know is that I want to decode it.
Here's one approach using jQuery that popped into my head:
function decodeHtml(html) {
return $('<div>').html(html).text();
}
That seems (very) hacky, though. What's a better way? Is there a "right" way?
This is my favourite way of decoding HTML characters. The advantage of using this code is that tags are also preserved.
function decodeHtml(html) {
var txt = document.createElement("textarea");
txt.innerHTML = html;
return txt.value;
}
Example: http://jsfiddle.net/k65s3/
Input:
Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>
Output:
Entity: Bad attempt at XSS:<script>alert('new\nline?')</script><br>
Don’t use the DOM to do this if you care about legacy compatibility. Using the DOM to decode HTML entities (as suggested in the currently accepted answer) leads to differences in cross-browser results on non-modern browsers.
For a robust & deterministic solution that decodes character references according to the algorithm in the HTML Standard, use the he library. From its README:
he (for “HTML entities”) is a robust HTML entity encoder/decoder written in JavaScript. It supports all standardized named character references as per HTML, handles ambiguous ampersands and other edge cases just like a browser would, has an extensive test suite, and — contrary to many other JavaScript solutions — he handles astral Unicode symbols just fine. An online demo is available.
Here’s how you’d use it:
he.decode("We're unable to complete your request at this time.");
→ "We're unable to complete your request at this time."
Disclaimer: I'm the author of the he library.
See this Stack Overflow answer for some more info.
If you don't want to use html/dom, you could use regex. I haven't tested this; but something along the lines of:
function parseHtmlEntities(str) {
return str.replace(/&#([0-9]{1,3});/gi, function(match, numStr) {
var num = parseInt(numStr, 10); // read num as normal number
return String.fromCharCode(num);
});
}
[Edit]
Note: this would only work for numeric html-entities, and not stuff like &oring;.
[Edit 2]
Fixed the function (some typos), test here: http://jsfiddle.net/Be2Bd/1/
There's JS function to deal with &#xxxx styled entities:
function at GitHub
// encode(decode) html text into html entity
var decodeHtmlEntity = function(str) {
return str.replace(/&#(\d+);/g, function(match, dec) {
return String.fromCharCode(dec);
});
};
var encodeHtmlEntity = function(str) {
var buf = [];
for (var i=str.length-1;i>=0;i--) {
buf.unshift(['&#', str[i].charCodeAt(), ';'].join(''));
}
return buf.join('');
};
var entity = '高级程序设计';
var str = '高级程序设计';
let element = document.getElementById("testFunct");
element.innerHTML = (decodeHtmlEntity(entity));
console.log(decodeHtmlEntity(entity) === str);
console.log(encodeHtmlEntity(str) === entity);
// output:
// true
// true
<div><span id="testFunct"></span></div>
jQuery will encode and decode for you.
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>
<script>
$(document).ready(function() {
$("#encoded")
.text(htmlEncode("<img src onerror='alert(0)'>"));
$("#decoded")
.text(htmlDecode("<img src onerror='alert(0)'>"));
});
</script>
<span>htmlEncode() result:</span><br/>
<div id="encoded"></div>
<br/>
<span>htmlDecode() result:</span><br/>
<div id="decoded"></div>
_.unescape does what you're looking for
https://lodash.com/docs/#unescape
This is so good answer. You can use this with angular like this:
moduleDefinitions.filter('sanitize', ['$sce', function($sce) {
return function(htmlCode) {
var txt = document.createElement("textarea");
txt.innerHTML = htmlCode;
return $sce.trustAsHtml(txt.value);
}
}]);

Error with custom Search and Replace function for Google Sites

I'm trying to use a script to replace a particular string with a different string. I think the code is right, but I keep getting the error "Object does not allow properties to be added or changed."
Does anyone know what could be going wrong?
function searchAndReplace() {
var teams = SitesApp.getPageByUrl("https://sites.google.com/a/directory/teams");
var list = teams.getChildren();
list.forEach(function(element){
page = element.getChildren();
});
page.forEach(function(element) {
var html = element.getHtmlContent();
html.replace(/foo/, 'bar');
element.setHtmlContent = html;
});
};
Try This:
Javascript reference:
The replace() method returns a new string with some or all matches of a pattern replaced by a replacement.
I think the issue here is that forEach cannot change the array that it is called upon. From developer.mozilla.org "forEach() does not mutate the array on which it is called (although callback, if invoked, may do so)."
Try doing it with a regular loop.

Newlines in Google App Script Embedded in Google Site?

I'm a newb, so there's probably something obvious that I'm missing...
This code is embedded in a Google Site that my company uses.
Basically, what I've done is to create a text box where I past in a SAML Response, I click the button and it URL Decodes and then base64 decodes the string. That works (surprisingly). But the output is just a long line of the XML. To get past this in python for example, I just replaced the "><" instances with ">\n<" and it formats it good enough for me. (I don't need a true XML format)
I have tried too many things to list here, but either the things I've guessed at don't work, the formatting gets unreadable, it cuts off the text and doesn't word wrap, etc. The current state does what I want, it just runs off the right side of the page (I can copy paste it, other things I've tried I can not do that) and doesn't put a newline in between the "><" when I add something there to try it.
Here is my ratty code, please ignore the comments, it's just stuff I've tried.:
function doGet(e) {
var myapp = UiApp.createApplication().setTitle('CAML Response Decoder');
var testText = "Decoded Response Will Appear Here...";
var mygrid = myapp.createGrid(2, 2);
mygrid.setText(0, 0, 'SAML Response: ');
mygrid.setWidget(0, 1, myapp.createTextBox().setName("SAMLin"));
mygrid.setText(1, 0, 'Decoded: ');
// mygrid.setWidget(1, 1, myapp.createTextBox().setName("SAMLout"));
mygrid.setWidget(1, 1, myapp.createLabel(testText).setWordWrap(true).setId("SAMLout"));
// mygrid.setWidget(1, 1, myapp.createHTML(testText).setId("SAMLout").setWordWrap(true).setWidth(50));
var mybutton = myapp.createButton('Decode');
// var mypanel = myapp.createVerticalPanel().setSize(800,500);
var mypanel = myapp.createHorizontalPanel();
mypanel.add(mygrid);
mypanel.add(mybutton);
myapp.add(mypanel);
var handler = myapp.createServerHandler('myClickHandler');
mybutton.addClickHandler(handler);
handler.addCallbackElement(mygrid);
return myapp;
}
function myClickHandler(e) {
var app = UiApp.getActiveApplication();
var textValue = e.parameter.SAMLin;
var strURIDecoded = textValue.replace(/%2D/g, "-").replace(/%5F/g, "_").replace(/%2E/g, ".").replace(/%21/g, "!").replace(/%7E/g, "~").replace(/%2A/g, "*").replace(/%27/g, "'").replace(/%28/g, "(").replace(/%29/g, ")").replace(/%3Cbr%20%2F%3E/g, "%0D" ).replace(/%0A/g, "%0D" ).replace(/%250D/g, "%0D").replace(/%5Cr%5Cn/g, "%0D").replace(/%2B/g, "+").replace(/%5Cn/g, "%0D").replace(/%5Cr/g, "%0D").replace(/%3D/g, "=");
var strB64Decoded = Utilities.base64Decode(strURIDecoded);
var Assertion = Utilities.newBlob(strB64Decoded).getDataAsString();
var AllDone = Assertion.replace(/></g, ">\n<");
// var AllDone = ("<div>" + AllDone2 + "</div>");
// var document = XmlService.parse(Assertion);
// var AllDone = XmlService.getCompactFormat()
// .setLineSeparator('\n')
// .setEncoding('UTF-8')
// .setIndent(' ')
// .format(document);
app.getElementById('SAMLout').setText(AllDone)
app.close();
return app;
}
I don't think the label will allow anything that would create a new line. You did try .createHTML which allows basic markup. Try using HTML with a <br> tag.
Line Break documentation - MDN
I haven't tried it, so I don't know if it works.
Other than that, I think you'd need to break up the content, and add a second label.
I figured it out. I ended up using the .createHTML and then replacing all of the "<" and ">" with another character. It was all due to this being XML and Google Sites stripping out things that they don't like. I'd love to hear other solutions though as this is quite a messy solution.

Extract the contents of a div using Flash AS3

I have a SFW embedded in a PHP page. There is also a div on the page with id="target".
I want to access the content of that div (ie: the characters inside it) and hold them as a String variable in AS3. How can I do this?
My attempt so far
import flash.external.ExternalInterface;
var myDivContent = ExternalInterface.call("function(){ return document.GetElementById('target');}");
var myDivContent2:String = myDivContent.toString();
test_vars.text = myDivContent2; //Dynamic text output
I don't think you can define a function in the ExternalInterface.call() method. You have to call a function by name which already exists in the JavaScript.
So I'd create some JavaScript code like this:
function getTargetContent()
{
return document.getElementById('target').innerHTML;
}
And then in your Flash,
var myDivContent = ExternalInterface.call("getTargetContent");
Note that document.getElementById('target') only returns the reference to that div, not the contents within. So if you don't return .innerHTML then the Flash will get an object which may not be usable (although I haven't actually tried doing this).
The easiest way to do this is as Allan describes, write a Javascript function to sit on the page and return the required value to you.
Of course, if you can't edit the page content, only the flash, then you do need to pass the function itself, which will actually have to be forced into the page though JavaScript injection. An example for your case, which I have not tested:
//prepare the JavaSctipt as an XML object for Dom insertion
var injectCode:XML =
<script>
<![CDATA[
function() {
getElementContent = function(elementID) {
return document.getElementById(elementID).innerHTML;
}
}
]]>
</script>;
//inject code
ExternalInterface.call(injectCode);
//get contents of 'divA'
var divAContent:String = ExternalInterface.call('getElementContent','divA') as String;
//get contents of 'spanB'
var spanBContent:String = ExternalInterface.call('getElementContent','spanB') as String;
You're almost there :
var res : String = ExternalInterface.call("function(){return document.getElementById('target').outerHTML}");
If you only want the content of your target, use innerHTML instead of outerHTML.

jsf messages: adding link

Currently in JSF, all HTML contained within a message (rich:messages tag) is escaped and just shows up as the markup. For example, in my backing bean, I have:
createMessage("Title created successfully with product number: " + product.getProductNumber() + ".");
where createMessage() is just a helper function that adds a new Message to the faces context and is then viewable in my rich:messages tag.
When this message is created, my message simply shows up with the escaped HTML:
Title created successfully with product number: 1234.
Is there any way to avoid this and just provide an actual link in the message instead?
Thanks in advance
~Zack
A quick solution is to create a new renderer.
I've done this for h:messages as I wanted to separate the messages of different severities into separate divs. If you never want to use the default renderer then it's a good option.
The standard class that you would overwrite/extend is:
public class MessagesRenderer extends HtmlBasicRenderer
You would just use a ResponseWriter that doesn't escape the text. The concrete class is the HtmlResponseWriter which escapes the text. You could extend this and overwrite the
public void writeText(Object text, String componentPropertyName)
so that it doesn't use HtmlUtils.
Then just add your new renderer to faces-config.xml
<render-kit>
<renderer>
<component-family>javax.faces.Messages</component-family>
<renderer-type>javax.faces.Messages</renderer-type>
<renderer-class>com.mypackage.MessagesRenderer</renderer-class>
</renderer>
</render-kit>
It sounds like you need to create your own version of rich:messages that has an escape attribute, like h:outputText, so you can disable HTML escaping.
If you're using jquery you can unescape the xml characters:
<script type="text/javascript">
//<![CDATA[
$(document).ready(function() {
$(".esc").each(function(i) {
var h = $(this).html();
h = h.replace(/</gi, "<");
h = h.replace(/>/gi, ">");
$(this).html(h);
});
});
//]]>
</script>