AMFPHP & NetConnection Call.BadVersion

If you used at least one time AMFPHP you probably had already encountered the NetConnection Call.BadVersion message.
This seems to be a very common issue for anyone who’s beginnig to develop with Flash Remoting in PHP. In fact I often read message from guys who had this this error while trying to use AMFPHP remoting.
The reasons of this error are often the same or at least similar, for this reason I thought to create a page on the wiki space about this problem.
This is a list of all the common situation where the Call.BadVersion appears. I get most of the poits reading people’s posts and I hope you will contribute to create the most comprehensive list about this common problem.

Other useful resources about AMFPHP:
AMFPHP installation guide
Flash-DB tutorial
Installation tips on amfphp.org

Link: http://www.sephiroth.it/phpwiki/index.php/Call.BadVersion

wxPython and Flash, first test


Today I make the first test integrating a Flash movie into a python application and using a communication between the two applications using FSCommand and the flashvars.
The result (surprendent easy) it’s a simple movie which enables text files saving in the local computer (through a prompt dialog window), but it has already opened my mind to future real cool applications 😉

This is the python code, the core part it’s the “wx.lib.flashwin” import, which enable to use Flash ActiveX in a python frame

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import wx, sys, os
import string, codecs
from wx.lib.flashwin import FlashWindow
from wx.lib.flashwin import EVT_FSCommand
#----------------------------------------

class TestPanel(wx.Panel):
    def __init__(self, parent, base, swf):
        wx.Panel.__init__(self, parent, -1)
        self.base = base
        sizer = wx.BoxSizer(wx.VERTICAL)
        self.flash = FlashWindow(self, style=wx.SUNKEN_BORDER)   
        dlg = wx.MessageDialog(self, "This will work only under Windows!","Warning!",wx.OK | wx.ICON_INFORMATION)
        dlg.Center()
        dlg.ShowModal()        
        wx.BeginBusyCursor()
        try:
            self.flash.LoadMovie(0, swf)
        except:
            wx.MessageDialog(self, "could not load the swf file","Error",wx.OK | wx.ICON_ERROR).ShowModal()
            sys.exit(2)
        wx.EndBusyCursor()        
        self.flash.Stop()      
        self.flash.SetSize((self.flash.GetSize()[0],self.flash.GetSize()[1]))
        # sizer
        sizer.Add(self.flash, 1, wx.EXPAND)
        self.SetSizer(sizer)
        self.SetAutoLayout(True)
        sizer.Fit(self)
        sizer.SetSizeHints(self)        
        self.SetFlashOptions()
        self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
        self.Bind(EVT_FSCommand, self.CallMethod)
        
    def SetFlashOptions(self):
        self.flash.menu = False
        self.flash._set_FlashVars("data=Server started on " + sys.platform)
        self.flash.Play()
        
    def OnDestroy(self, evt):
        if self.flash:
            self.flash.Cleanup()
            self.flash = None

    # Called from Flash FSCommand
    def CallMethod(self, evt):
        try:
            arguments = string.split(evt.args,"###")
            filename = arguments[0]
            body = arguments[1]
            if filename == "" or body == "":
                wx.MessageDialog(self, "Please check data inserted", "An Error occurred", wx.OK | wx.ICON_INFORMATION).ShowModal()
            else:
                dlg = wx.FileDialog(self, "Save as..." , os.getcwd(), filename, "*.*", wx.SAVE | wx.OVERWRITE_PROMPT )
                if dlg.ShowModal() == wx.ID_OK:
                    try:
                        f = codecs.open(os.path.normpath(dlg.GetPath()), "w", "utf-8", "ignore")
                        f.write(codecs.utf_8_decode(codecs.BOM_UTF8)[0])
                        f.write(body)
                        f.close()
                        self.flash._set_FlashVars("data=Succesfully saved text file")
                    except:
                        wx.MessageDialog(self, "%s %s %s" % sys.exc_info(), "An Error occurred", wx.OK | wx.ICON_ERROR).ShowModal()
                        self.flash._set_FlashVars("data=%s %s %s" % sys.exc_info())
        except:
            wx.MessageDialog(self, "Please check data inserted","An Error occurred",wx.OK | wx.ICON_INFORMATION).ShowModal()
            self.flash._set_FlashVars("data=%s %s %s" % sys.exc_info())
#-------------------------------------------
if __name__ == '__main__':
    class TestFrame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, -1, "ActiveX -- Flash", size=(640, 480), style=wx.DEFAULT_FRAME_STYLE )
            base = os.path.normpath(os.path.abspath(os.path.dirname(sys.argv[0])))
            swf = os.path.normpath(os.path.join(base, "movie.swf"))
            self.tp = TestPanel(self, base, swf)
    app = wx.PySimpleApp()
    frame = TestFrame()
    frame.Center()
    frame.Show(True)    
    app.MainLoop()

the flash part is really easy. Two text field, one button and one line of code!:

on (click) {	fscommand("saveFile", this._parent.fnome.text + "###" + this._parent.ftesto.text)}

P.S. Moreover today I read in wxPython mailing list a coming new version of wxPython. I hope this will begin to fix varoius problems with Mac installation of SE|PY

CellRenderer tutorial

Today I commit a new version of the Serializer Class.
What is Serializer Class?
This Class enable you to pass and receive complex data type from and to PHP using the native PHP functions serialize and unserialize (this means that you can receive an array directly from PHP without making any kind of split to obtain your original array).

After committing I also wrote a little tutorial on how to pass a PHP Class Object to Flash and how to bind the received value into a datagrid component using the cellRenderer api in order to customize its fields, adding checkboxes, numeric stepper and images to it…

You can find the tutorial here:
http://www.sephiroth.it/tutorials/flashPHP/cellRenderer/
More info about the cellRenderer APIs can be found here:
http://livedocs.macromedia.com/…/Documentation&file=16_cell4.htm

XML2Object

This class, that is just a translation of a simple set of function written for Flash MX, translates any kind of XML document into a readable Flash Object. This could be the core for projects XML oriented..
in fact i work often on xml based projects…

/**
* @class it.sephiroth.XML2Object
* @author Alessandro Crugnola
* @version 1.0
* @description return an object with the content of the XML translated
* NOTE: a node name with "-" will be replaced with "_" for flash compatibility.
* for example  will become FIRST_NAME
* If a node has more than 1 child with the same name, an array is created with the children contents
* The object created will have this structure:

* 	- obj {

*		nodeName : {

*			attributes : an object containing the node attributes

*			data : an object containing the node contents

*	}

* @usage data = new XML2Object().parseXML( anXML);
*/
//import utils.string

class it.sephiroth.XML2Object extends XML {
	private var oResult:Object = new Object ();
	private var oXML:XML;
	/**
	* @method get xml
	* @description return the xml passed in the parseXML method
	* @usage theXML = XML2Object.xml
	*/
	public function get xml():XML{
		return oXML
	}
	/**
	* @method public parseXML
	* @description return the parsed Object
	* @usage XML2Object.parseXML( theXMLtoParse );
	* @param sFile XML
	* @returns an Object with the contents of the passed XML
	*/
	public function parseXML (sFile:XML):Object {
		this.oResult = new Object ();
		this.oXML = sFile;
		this.oResult = this.translateXML();
		return this.oResult;
	}
	/**
	* @method private translateXML
	* @description core of the XML2Object class
	*/
	private function translateXML (from, path, name, position) {
		var xmlName:String;
		var nodes, node, old_path;
		if (path == undefined) {
			path = this;
			name = "oResult";
		}
		path = path[name];
		if (from == undefined) {
			from = new XML (this.xml);
			from.ignoreWhite = true;
		}
		if (from.hasChildNodes ()) {
			nodes = from.childNodes;
			if (position != undefined) {
				var old_path = path;
				path = path[position];
			}
			while (nodes.length > 0) {
				node = nodes.shift ();
				xmlName = node.nodeName.split("-").join("_");
				if (xmlName != undefined) {
					var __obj__ = new Object ();
					__obj__.attributes = node.attributes;
					__obj__.data = node.firstChild.nodeValue;
					if (position != undefined) {
						var old_path = path;
					}
					if (path[xmlName] != undefined) {
						if (path[xmlName].__proto__ == Array.prototype) {
							path[xmlName].push (__obj__);
							name = node.nodeName;
							position = path[xmlName].length - 1;
						} else {
							var copyObj = path[xmlName];
							path[xmlName] = new Array ();
							path[xmlName].push (copyObj);
							path[xmlName].push (__obj__);
							name = xmlName;
							position = path[xmlName].length - 1;
						}
					} else {
						path[xmlName] = __obj__;
						name = xmlName;
						position = undefined;
					}
				}
				if (node.hasChildNodes ()) {
					this.translateXML (node, path, name, position);
				}
			}
		}
		return this.oResult;
	}
}

An Example usage with this file:
http://www.sephiroth.it/tutorials/flashPHP/indice.xml

import it.sephiroth.XML2Object;
var oXML:XML = new XML ();
var sXML:String = "indice.xml";
oXML.ignoreWhite = true;
function xmlLoaded (success:Boolean) {
        if (success) {
                trace (success);
                _root.ObjFromXML = new XML2Object ().parseXML (this);
                delete this
        }
}
oXML.onLoad = xmlLoaded;
oXML.load (sXML);

undefined toString??

One of the things that it has always made me laugh on the new Flash AS2 is the translation of the undefined value (mmhh.. not a value, it’s undefined!).

a = undefined;trace(a.toString()) // undefined

b = a + " is not a string"trace(b) // "undefined is not a string"

???
Probably I don’t yet understand the strict data typing concept (quite sure), but undefined CAN’T be converted to "undefined".
It’s so Stupid for me!

So Cool in Bratislava and Cracovia

Welcome back to everyone,
I spent fantastic days in Slovakia, Czech Republic and Poland!
I hope you all had a good holdays this year..
I falled in love with this two cities and I’m sure I will come back as soon as possible for a week-end or holidays.
Weather wass very cold (-10° C), it’s always snowing, but people (girls expecially), beer and food are superbs!
We’ve drunk and eat everyday in every hour 🙂

P.S. I met a fantastic girl in Bratislava, in the Café Studio Club! I have to learn Slovakian language now.. the problem is that it’s not OOP 😉

A PHP domxml class in flash style!

Some days ago Daniele, a friend of mine, point my attention to an opensource project hosted on sourceforge that is very interesting for PHP/Flash guys 🙂
This module permit to do an xml parsing, in PHP, using a dom xml in the same way we already do in flash.

Here a little example i made using this class:

<?
// include the php module
include('lib.xml.inc.php');
// load an external xml source
$test = new XML('test.xml');

// make a simple parsing, in AS style ;)
$childs = $test->firstChild->childNodes;
for($a = 0; $a < count($childs); $a++){	
echo "nodeName " . $childs[$a]->nodeName . "<br />";	
echo "nodeValue " . $childs[$a]->firstChild->nodeValue . "<br />";
}
?>

as you can see, we’re already familiar with firstChild, nodeName, nodeValue… etc..
I always hate the PHP SAX parser, and always always prefer a dom xml parser, much more simple to create and to read.

A* PathFinder for Flash

Use the A* algorithm to create a path finder for your flash games.
The A* can be summarized as:

    setup the openlist (an array)
    setup the closedlist (an array)
    push the starting node to the open list (node is a square in our grid)
    while the openlist is not empty
        Look for the lowest 'f' cost node on the open list and pop from the openlist and name it 'current'
        if the current node is the goal then we found the solution, exit the while loop
        for each of the node adjacent to the current node (8 is we allow diagonal movement)
        set the parent of this adjacent to 'current'
                if a node with the same position as the adjacent node is in the open list /
                and its 'f' is lower than the node adjacent
                        then skip current adjacent node
                if a node with the same position is in closedlist /
                and its 'f' is lower
                        then skip current adjacent node
                otherwise push the current node to the open list
                remove occurences of adjacent node from OPEN and CLOSED list
                Add adjacent node to the OPEN list
        end for
        add the current node to the closed list
    end while

Read the article on my wiki
View the working example