Get the byte length of a string - actionscript-3

Is there an easy way to get the byte length of a string in AS3? String.length works in many cases, but breaks if it encounters mulibyte unicode characters.
(in this particular case, I need to know this so I can preface messages sent across a TCP socket with the message length. This is in standard netstring format e.g. "length:message,").

Use a ByteArray like so:
var b:ByteArray = new ByteArray();
b.writeUTFBytes("This is my test string");
trace("Byte length: " + b.length);
Info on ByteArray here: http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/utils/ByteArray.html

Related

How to replace special symbols in a binary?

I am trying to read a pdf from a URL, return it as a binary and replace some characters. This is working for plain text with the following code but if the pdf has any special symbols like Trademark, copyright etc then my webservice is unable to return the result. Can some one please help me how to achieve this. The output should definitely be a binary output :
String html="";
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream in = new URL(jsonobj.getString("xBody")).openStream();
int reads = in.read();
while(reads != -1){
baos.write(reads);
reads = in.read();
}
html= baos.toString();
The method baos.toString() internally calls new String(buffer), which uses the default encoding (the encoding actually being used by your system, probably not UTF-8). Try to provide the encoding explicitly, as follows:
String html = new String(baos.toByteArray(), "UTF-8");

problems reading int from bytearray

This is my first question, so do not judge strictly.
I have an object that I'm getting from php server to as3(flash) client. That object is AMF encoded, so I write server response to ByteArray:
var ba:ByteArray = new ByteArray();
ba.writeUTFBytes( rawData );
and than I'm reading object from ByteArray:
ba.position = 0;
var response:Object = ba.readObject();
Part of object contains such data:
{
'money' : 900
}
And when reading object from ByteArray, I get a seven-digit number ~ 1824344 instead of 900. But when I get form server String '900' or int value equals 100 - data reads correctly.
Has someone had such a problem?
You have to read the same way you wrote. If you write something using writeUTFBytes(), you have to read it using readUTFBytes().
In this case you should use writeObject() and readObject() because you are writing pure Object but not String.

Using as3Crypto to encrypt/decrypt with only URL Query save chars

I was using as3Crypto with no probs
http://www.zedia.net/2009/as3crypto-and-php-what-a-fun-ride/
but it produces a string which includes equal (and probably other URL Query unsafe characters). Is there a way to encrypt like this?
Current code below:
public function encrypt(txt:String = ''):String
{
var data:ByteArray = Hex.toArray(Hex.fromString(txt));
var pad:IPad = new PKCS5;
var mode:ICipher = Crypto.getCipher(type, key, pad);
pad.setBlockSize(mode.getBlockSize());
mode.encrypt(data);
return ''+Base64.encodeByteArray(data);
}
Yes, base 64 encoding is the normal way to do this, although you must still URL escape the result, because Base64 contains unsafe characters as well ('/', '+' and '=' to be precise).

AS3: Use the underscore character in a URLVariables variable name

Is it possible to use the underscore character in a URLVariables variable name? For instance, the following code outputs "my%5Fusername=foo" instead of "my_username=foo".
import flash.net.URLVariables;
var variables : URLVariables = new URLVariables("my_username=foo");
trace(variables.toString());
Just as in the trace, the "%5F" shows up instead of the underscore in the request. Is there some way I can get the underscore character to show up instead?
Simply don't use URLVariables class, it's known to do other things wrong too. This URL RFC calls the underscore a special character and puts it in the same category as alphanumeric, saying that no encoding is needed. This RFC calls the part where you'd have the variables as "query" and allocates pchar to it, describing pchar as containing underscore character.
In practice URI containing underscore characters doesn't seem to give problem to browsers or servers, so it's just plain wrong to encode it.
EDIT: from further reading it looks more like that this is rather an undesirable behavior, then a mistake (the URI normalizer would know to revert the encoded underscore to it's original look), still, encoding underscore is the same as encoding letters of English alphabet - wasteful and stupid.
Using a regular expression, you can convert the output to underscore. This method takes advantage of the facts that:
URLRequest's data variable is a generic Object
String is an Object
output of toString() and replace() are String objects 3.
The code:
var url:String = "http://www.[yourDomain].com/test";
var request:URLRequest = new URLRequest(url);
var variables:URLVariables = new URLVariables("my_user_name=f_o_o");
// add some more variables:
variables.exampleSessionId = "test";
variables.example_Session_Id2 = "test2";
// set up the search expression:
var undPatrn:RegExp = /%5f/gi;
trace("Without '_': " + variables.toString());
trace("With '_': " + variables.toString().replace(undPatrn, "_"));
trace(variables);
// navigate with %5f:
request.data = variables.toString();
navigateToURL(request);
// navigate with underscore:
request.data = variables.toString().replace(undPatrn, "_");
navigateToURL(request);
trace(unescape(variables.toString()));

Strange Base64 encode/decode problem

I'm using Grails 1.3.7. I have some code that uses the built-in base64Encode function and base64Decode function. It all works fine in simple test cases where I encode some binary data and then decode the resulting string and write it to a new file. In this case the files are identical.
But then I wrote a web service that took the base64 encoded data as a parameter in a POST call. Although the length of the base64 data is identical to the string I passed into the function, the contents of the base64 data are being modified. I spend DAYS debugging this and finally wrote a test controller that passed the data in base64 to post and also took the name of a local file with the correct base64 encoded data, as in:
data=AAA-base-64-data...&testFilename=/name/of/file/with/base64data
Within the test function I compared every byte in the incoming data parameter with the appropriate byte in the test file. I found that somehow every "+" character in the input data parameter had been replaced with a " " (space, ordinal ascii 32). Huh? What could have done that?
To be sure I was correct, I added a line that said:
data = data.replaceAll(' ', '+')
and sure enough the data decoded exactly right. I tried it with arbitrarily long binary files and it now works every time. But I can't figure out for the life of me what would be modifying the data parameter in the post to convert the ord(43) character to ord(32)? I know that the plus sign is one of the 2 somewhat platform dependent characters in the base64 spec, but given that I am doing the encoding and decoding on the same machine for now I am super puzzled what caused this. Sure I have a "fix" since I can make it work, but I am nervous about "fixes" that I don't understand.
The code is too big to post here, but I get the base64 encoding like so:
def inputFile = new File(inputFilename)
def rawData = inputFile.getBytes()
def encoded = rawData.encodeBase64().toString()
I then write that encoded string out to new a file so I can use it for testing later. If I load that file back in as so I get the same rawData:
def encodedFile = new File(encodedFilename)
String encoded = encodedFile.getText()
byte[] rawData = encoded.decodeBase64()
So all that is good. Now assume I take the "encoded" variable and add it to a param to a POST function like so:
String queryString = "data=$encoded"
String url = "http://localhost:8080/some_web_service"
def results = urlPost(url, queryString)
def urlPost(String urlString, String queryString) {
def url = new URL(urlString)
def connection = url.openConnection()
connection.setRequestMethod("POST")
connection.doOutput = true
def writer = new OutputStreamWriter(connection.outputStream)
writer.write(queryString)
writer.flush()
writer.close()
connection.connect()
return (connection.responseCode == 200) ? connection.content.text : "error $connection.responseCode, $connection.responseMessage"
}
on the web service side, in the controller I get the parameter like so:
String data = params?.data
println "incoming data parameter has length of ${data.size()}" //confirm right size
//unless I run the following line, the data does not decode to the same source
data = data.replaceAll(' ', '+')
//as long as I replace spaces with plus, this decodes correctly, why?
byte[] bytedata = data.decodeBase64()
Sorry for the long rant, but I'd really love to understand why I had to do the "replace space with plus sign" to get this to decode correctly. Is there some problem with the plus sign being used in a request parameter?
Whatever populates params expects the request to be a URL-encoded form (specifically, application/x-www-form-urlencoded, where "+" means space), but you didn't URL-encode it. I don't know what functions your language provides, but in pseudo code, queryString should be constructed from
concat(uri_escape("data"), "=", uri_escape(base64_encode(rawBytes)))
which simplifies to
concat("data=", uri_escape(base64_encode(rawBytes)))
The "+" characters will be replaced with "%2B".
You have to use a special base64encode which is also url-safe. The problem is that standard base64encode includes +, / and = characters which are replaced by the percent-encoded version.
http://en.wikipedia.org/wiki/Base64#URL_applications
I'm using the following code in php:
/**
* Custom base64 encoding. Replace unsafe url chars
*
* #param string $val
* #return string
*/
static function base64_url_encode($val) {
return strtr(base64_encode($val), '+/=', '-_,');
}
/**
* Custom base64 decode. Replace custom url safe values with normal
* base64 characters before decoding.
*
* #param string $val
* #return string
*/
static function base64_url_decode($val) {
return base64_decode(strtr($val, '-_,', '+/='));
}
Because it is a parameter to a POST you must URL encode the data.
See http://en.wikipedia.org/wiki/Percent-encoding
paraquote from the wikipedia link
The encoding used by default is based
on a very early version of the general
URI percent-encoding rules, with a
number of modifications such as
newline normalization and replacing
spaces with "+" instead of "%20"
another hidden pitfall everyday web developers like myself know little about