AMFPHP issue referencing ByteArray

Recently I made some test in AMFPHP sending an retrieving ByteArray to be stored in a mysql blob field.

But suddenly I encounter a problem when I was trying to return an array of ByteArrays and I could not find out the reason flash continued to show me this error:

The php file which was generating this error was:

class Service
{
public function getArray( )
{
$GLOBALS['amfphp']['encoding'] = 'amf3';
$a = new ByteArray("\x00\x10this is a string");
$b = new ByteArray("\x00\x16this is another string");
$c = $a;
return array( $a, $b, $c );
}
}

While the Actionscript test class was:

package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
import flash.net.Responder;
import flash.utils.ByteArray;

public class test extends Sprite
{
private var nc: NetConnection;
private var rsp: Responder;

public function test()
{
rsp = new Responder( onResult, null );
nc = new NetConnection();
nc.objectEncoding = ObjectEncoding.AMF3;
nc.connect( "http://localhost/amfphp/trunk/gateway.php" );
nc.call( "test.bytearray.Service.getArray", rsp );
}

private function onResult( e: * ): void
{
if ( e is Array )
{
for each ( var b: ByteArray in( e as Array ) )
{
trace( 'reading bytearray...' );
b.position = 0;
trace( b.readUTF() );
}
}
}
}
}


After some investigation I found that the error was into the AMFSerializer.php file in the writeAmf3ByteArray method which doesn’t reference correctly the bytearray objects.

Thus I made a little modification and after that I succeeded to retrieve correctly the bytearray list ( with the 3rd element as reference of the first one ).

Here you can download the patch file, if you want to test the modification ( at your own risk 🙂 ). The patch has been created using the last svn version of amfphp and you can apply the patch with the following command:
patch -p0 -i bytearray.patch

AMFPHP and mbstring

These days I was working on a flex 2/amfphp project and I discovered a very strange issue accidentally.
With PHP 5.2.4 installed both on local and remote server, the local amfphp works and the remote gave errors.

Connecting to the service browser I was receiving the error “Channel.Ping.Failed” error and investingating a bit more in the fault message I discovered that the source error was:

The class {Amf3Broker} could not be found under the class path {/var/htdocs/amfphp/services/amfphp/Amf3Broker.php}

and the Amf3Broker php class does not exists anywhere in amfphp! But in the Actions.php file on line 78 I found this:
if(!$handled)
{
$uriclasspath = "amfphp/Amf3Broker.php";
$classpath = $baseClassPath . "amfphp/Amf3Broker.php";
$classname = "Amf3Broker";
$methodname = "handleMessage";
}

That’s the strange thing because the $handled variable should be true ’cause usually the first request sent by flash is a $messageType = “flex.messaging.messages.CommandMessage”. So I continued in my investigation logging all the messages that php was receiving.
So at the end I discovered that amfphp didn’t deserialize the amf data correctly! All the packet were corrupted (that’s why $messageType wasn’t handled), all the strings were not correctly parsed.
Finally I discovered the reason. It’s because mbstring.
The only difference between the remote server and the local server is the php.ini setting about mbstring overload and the others mbstring settings.
The remote server has mbstring.func_overload = 2, that means all the strings functions are affected and that’s why the amfphp methods were returing corrupted data.
In fact I just changed this method into AMFDeserializer.php:
function readBuffer($len)
{
$data = substr($this->raw_data,$this->current_byte,$len);
$this->current_byte += $len;
return $data;
}

into:
function readBuffer($len)
{
$data = "";
for($i = 0; $i < $len; $i++) { $data .= $this->raw_data{$i + $this->current_byte};
}
$this->current_byte += $len;
return $data;
}

and the original error disappeared! Obviously I got other errors later, that’s because there are many other string functions in amfphp.. but at least I found the cause.

In fact, removing the mbstring.func_overload in the php.ini everything worked again!

AMFPHP 1.9 changes and future plans

Recently Patrick released a new testing version of AMFPHP which supports the Flex2 AMF3 object encoding.

Some changes:

$this->methodTable is DEAD. All methods in /services are now considered remotely accessible, unless you set them to protected or private (PHP5) or start the method name with an (_)
– Returning a mysql_query will now return either an Array or an ArrayCollection depending on the setting in gateway.php
– browser now brings up the brand spanking new Flex 2-based service browser

This is a testing version since it has still a lot of limitations and it has been tested only on PHP5. I see the post today and I haven’t tested yet…
You can read here for a detailed list of changes

Moreover Patrick plans to add to amfphp the Flex Data Services (read what they are). In this post he got a brief explanation about flash player/FDS communication and ask for developers to help him with the developement of FDS in amfphp (you might need a copy of charles).