I am using ExternalInterface in Flex to retrieve AMF encoded string from Javascript. The problem is the AMF encoded string sometimes contains \u0000 which causes the ExternalInterface to return null instead of the encoded string from Javascript.
Any idea how to solve this?
Thanks in advance.
The \0000 is falsely interpreted as EOF when reading external data. The same thing happens when it appears in XML files, as well.
You should be able to replace it with an unambiguous character sequence before passing the string to Flash, and back upon reception in ActionScript. In the JavaScript function, use something like
return returnString.replace (/\0000/g, "{nil}");
This should remove the unwanted \0000 characters from the string before returning it to Flash.
On the Flash side, use
receiveString = receiveString.replace (/\{nil\}/g, "\u0000");
directly after receiving the data.
Encoding the pyamf AMF output to base64 will do the trick.
Here is the encoding part in python:
encoder = pyamf.get_encoder(pyamf.AMF3)
encoder.writeObject(myObject)
encoded = base64.b64encode(encoder.stream.getvalue())
Here is the decoding part in AS3:
var myDecoder:Base64Decoder = new Base64Decoder();
myDecoder.decode(base64EncodedString);
var byteArr:ByteArray = myDecoder.toByteArray()
byteArr.position = 0;
var input:Amf3Input = new Amf3Input();
input.load(byteArr);
var test:MyObject = input.readObject();
Related
I used this base64 and uriencode on a number
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/core-min.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js"></script>
<script>
var num= '1418265869452';
var base64num = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(salt));
var encodeuri = encodeURIComponent(base64num);
</script>
base64 num gives me MTQxODI2NTg2OTQ1Mg==
But actually i also needs to uri encode it after base64 encode
when i tried to encodeURIComponent(base64num) it throwed me an error as follows:
Exception thrown from JavaScript : Error: Malformed UTF-8 data
How to achieve this
I've never seen encodeURIComponent throw JS errors. Its probably someplace in the third party library. Depending on your browser support requirements you might be able to use the built in base64 encoder/decoders
var base64num = btoa('1418265869452'),
encodeuri = encodeURIComponent(base64num);
encodeuri; // "MTQxODI2NTg2OTQ1Mg%3D%3D"
This could also be happening when you try to decode it. First you have to decodeURIComponent before trying to base64 decode it.
You are passing salt variable as a parameter, but I am not seeing any initialization of it. Instead you need to pass num, then it will start working, as I have used num in place of salt and is working perfectly fine at my end.
Here is the updated JSFiddle Link
Updated Code:
var num= '1418265869452';
var base64num = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(num));
var encodeuri = encodeURIComponent(base64num);
alert(encodeuri);
So, I have a some json data which I create in my controller like so:
Notes = JsonConvert.SerializeObject(contact.Notes.OrderBy(x => x.DateLogged).Select(x => new
{
id = x.Id,
date = x.DateLogged,
content = x.Content,
logged = x.Username
}))
This then gets passed to the view, now which statment can I do to achieve the results of having a variable contain that json data:
var data = '#Html.Raw(Model.Notes)'
or
var data = JSON.parse('#Html.Raw(Model.Notes)');
EDIT
the content variable holds some "\n" which when passed to the view using the first choice from above generates an error, saying
Unexpected Token
it only does it with \n so what is going wrong here? the bottom method doesn't quite work.
var data = JSON.parse('#Html.Raw(Model.Notes)');
This doesn't work - you can't put a JSON literal inside a JavaScript string. Any backslash in it will be an escape character to the JavaScript parser, not the JSON parser. A newline comes out like:
var data = JSON.parse('{"content": "abc\ndef"}');
which means the string you are asking JSON to parse is:
{"content": "abc
def"}
which is not valid as you can't have a literal newline in a JSON string.
To do this with JSON.parse you would have to JS-string-literal encode the JSON output, so you would end up with "abc\\ndef". The alternative would be to include the JSON directly in the script block as var data = #Html.Raw(Model.Notes);, but there are problems with this to do with the differences between JS and JSON (primarily characters U+2028 and U+2029) and the enclosing HTML context (ie what the sequence </script does).
Getting the escaping right here is harder than it looks, so you should avoid injecting anything into a <script> block. Better to put in-page JSON data in a data- attribute and read it from the DOM; this way you can use the normal HTML escaping Razor gives you by default.
<div id="notes" data-notes="#Model.Notes">
...
var data = JSON.parse(document.getElementById('notes').getAttribute('data-notes'));
bobince is obviously correct in what he says, it makes so much sense, thanks for that.
However, my solution was to simply do:
var data = #Html.Raw(Model.Notes);
Because, Newtonsoft already has converted it to a proper JSON format, so all it needs to do, is be assigned to a variable to be manipulated.
I think grabbing the content from a the HTML DOM is a bit too much for this.
I'm trying to decode a base64 string for an image back into binary so it can be downloaded and displayed locally by an OS.
The string I have successfully renders when put as the src of an HTML IMG element with the data URI preface (data: img/png;base64, ) but when using the atob function or a goog closure function it fails.
However decoding succeeds when put in here: http://www.base64decode.org/
Any ideas?
EDIT:
I successfully got it to decode with another library other than the built-in JS function. But, it still won't open locally - on a Mac says it's damaged or in an unknown format and can't get opened.
The code is just something like:
imgEl.src = 'data:img/png;base64,' + contentStr; //this displays successfully
decodedStr = window.atob(contentStr); //this throws the invalid char exception but i just
//used a different script to get it decode successfully but still won't display locally
the base64 string itself is too long to display here (limit is 30,000 characters)
I was just banging my head against the wall on this one for awhile.
There are a couple of possible causes to the problem. 1) Utf-8 problems. There's a good write up + a solution for that here.
In my case, I also had to make sure all the whitespace was out of the string before passing it to atob. e.g.
function decodeFromBase64(input) {
input = input.replace(/\s/g, '');
return atob(input);
}
What was really frustrating was that the base64 parsed correctly using the base64 library in python, but not in JS.
I had to remove the data:audio/wav;base64, in front of the b64, as this was given as part of the b64.
var data = b64Data.substring(b64Data.indexOf(',')+1);
var processed = atob(data);
I have moss service which output the url of image.
Lets say the output url has '&' character , the service appending amp; next to &.
for ex: Directory.aspx?&z=BWxNK
Here amp; is additionally added. it is a moss sevice. so i don't have control on the sevice.
what i can do is decode the output. As i am using Ajax calls for calling moss sevice i am forced to decode the out put from javascript. i tried decodeURIComponent,decodeURI,unescape. nothing solved the problem.
Any help greatly appreciated. even server side function also helpful. i am using Aspl.net MVC3
Regards,
Kumar.
& is not URI encoded, it's HTML encoded.
For a server side solution, you could do this:
Server.HtmlDecode("&") // yields "&"
For a JavaScript solution, you could set the html to "&" and read out the text, to simulate HTML decoding. In jQuery, it could look like this:
$("<span/>").html("&").text(); // yields "&"
& is SGML/XML/HTML for &.
If the service is outputting an XML document, then make sure you are using an XML parser to parse it (and not regular expressions or something equally crazy).
Otherwise, you need decode the (presumably) HTML. In JavaScript, the easiest way to do that is:
var foo = document.createElement('div');
foo.innerHTML = myString;
var url = foo.firstChild.data;
I am working on my open source project Downloadify, and up until now it simply handles returning Strings in response to ExternalInterface.call commands.
I am trying to put together a test case using JSZip and Downloadify together, the end result being that a Zip file is created dynamically in the browser, then saved to the disk using FileReference.save. However, this is my problem:
The JSZip library can return either a base64 encoded string of the Zip, or the raw byte string. The problem is, if I return that byte string in response to the ExternalInterface.call command, I get this error:
Error #1085: The element type "string" must be terminated by the matching end-tag "</string>"
ActionScript 3:
var theData:* = ExternalInterface.call('Downloadify.getTextForSave',queue_name);
Where queue_name is just a string used to identify the correct instance in JS.
JavaScript:
var zip = new JSZip();
zip.add("test.txt", "Hello world!\n");
var content = zip.generate(true);
return content;
If I instead return a normal string instead of the byte string, the call works correctly.I would like to avoid using base64 as I would have to include a base64 decoder in my swf which will increase its size.
Finally: I am not looking for a AS3 Zip generator. It is imperative to my project to have that part run in JavaScript
I am admittedly not a AS3 programmer by trade, so if you need any more detail please let me know.
When data is being returned from javascript calls it's being serialized into an XML string. So if the "raw string" returned by JSZip will include characters which make the XML non-valid, which is what I think is happening here, you'll get errors like that.
What you get as a return is actually:
<string>[your JSZip generated string]</string>
Imagine your return string includes a "<" char - this will make the xml invalid, and it's hard to tell what character codes will a raw byte stream translate too.
You can read more about the external API's XML format on LiveDocs
i think the problem is caused by the fact, that flash expects a utf8 String and you throw some binary stuff at it. i think for example 0x00FF will not turn out to be valid utf8 ...
you can try fiddling around with flash.system::System.setCodePage, but i wouldn't be too optimistic ...
i guess a base64 decoder is probably really the easiest ... i'd rather worry about speed than about file size though ... this rudimentary decoder method uses less than half a K:
public function decodeBase64(source:String):ByteArray {
var ret:ByteArray = new ByteArray();
var map:Object = new Object();
var i:int = 0;
for each (var char:String in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("")) map[char] = i++;
map["="] = 0;
source = source.split("\n").join("").split("\r").join("");//remove linebreaks
for (i = 0; i < source.length/4; i++) {
var buf:int = 0;
for each (char in source.substr(i * 4, 4).split("")) buf = (buf << 6) + map[char];
ret.writeByte(buf >>> 16);
ret.writeShort(buf);
}
return ret;
}
you could simply shorten function names and take a smaller image ... or use ColorTransform or ConvolutionFilter on one image instead of four ... or compile the image into the SWF for smaller overall size ... or reduce function name length ...
so unless you're planning on working with MBs of data, this is the way to go ...