apache mod_security oddity in AMFPHP

April 3rd, 2008

An AMFPHP user gave me a run for my money on debugging an error on a new server. Come to find out mod_security can play a little havoc on AMFPHP and even though the gateway.php file executes correctly. When you open up the amfphp/browser you will get the following error which will also be your fault event in your application.

(mx.rpc::Fault)#0  errorID = 0faultCode = "Client.Error.MessageSend"faultDetail = "Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed"faultString = "Send failed"message = "faultCode:Client.Error.MessageSend faultString:'Send failed' faultDetail:'Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed'"name = "Error"rootCause = (Object)#1code = "NetConnection.Call.Failed"

description = "HTTP: Failed"

details = "http://somedomain.com/amfphp/gateway.php"

level = "error"

when you call a service it gives the following error.

403 Forbidden

Forbidden

You don't have permission to access /amfphp/gateway.php on this server.

Additionally, a 404 Not Found

error was encountered while trying to use an ErrorDocument to handle the request.

Apache/1.3.39 Server at domainname.com Port 80

So if you are seeing this error when you try and connect to your gateway in charles / service capture look at a phpinfo page and see if mod_security is installed. If it is then in order to fix this error you need to create an .htaccess file in the amfphp/gateway.php directory and place the following content in it.

<ifmodule>SecFilterInheritance Off </ifmodule>

Hope that helps. If anyone knows more about this module please let me know what really is going on as I would love to understand why a security module is stopping amfphp.

AMFPHP, Flash Platform

Updated: crossdomain.xml fixes amfphp for april flash player release

March 31st, 2008

This updated crossdomain.xml example fixes all of the issues that people were having with the last post that I had. Please update your server with the following file. Remember that you need to remove any spaces as this has to be well formated xml! Make sure that you place the file in your web root directory of the top level domain of the site. This is commonly the public_html or www directory in the server so that you can access the file at www.yourdomain.com/crossdomain.xml

If you do not add this file you will get a Error #2044: Unhandled SecurityErrorEvent:. text=Error #2048: Security sandbox violation:
Which will toss an error that looks something like this out of the player.

Security sandbox error

crossdomain.xml










Again the purpose of a crossdomain.xml file is to allow external domains to access your content. What has changed in the new release is that we can not change the header anymore even if its on the same domain name. This means that you need to add a crossdomain file even if you are not accessing your amfphp installation from an external domain name. More information on policy files!

Policy file Syntax

Preparing for the Flash Player 9 April 2008 Security Update

AMFPHP, ActionScript 3, Flash Platform

Speaking at SWFCAMP: N-Tier Development with AMFPHP

March 31st, 2008

I am going to being making a presentation on AMFPHP at SWFCAMP which is put together by the Adobe users group mn.swf.  If you are going to be attending the confrence make sure you say hi! Also post a comment if there is something specific that you would like to hear about.

N-Tier Development with AMFPHP
In this session you will learn the basics of setting up an AMFPHP PHP environment. We will then walk through a CRUD (create, read, update, delete) example in both Flash CS3 and Flex. You should leave this session with confidence in starting to use AMFPHP in building your business logic and data tiers for future Flash Player based applications. Throughout the session we will describe some of the tips and tricks for optimizing AMFPHP with information on class mapping, Authentication, ArrayCollection’s, and AMFEXT, which will keep the attention of even the most veteran RIA developer.

AMFPHP, ActionScript 3, Flash Platform, Speaking

AMFPHP ArrayCollection

March 27th, 2008

AMFPHP does not natively convert Arrays to ArrayCollections, and there is no ArrayCollection class to speak of for PHP. You may sometimes need ArrayCollection typed values to be returned within a VO. There are three fixes that I’ve found for this.

Fix 1
If you are just expecting an ArrayCollection as the result of a PHP service call then simply create an ArrayCollection out of the returned Array from PHP. The following AS3 casts the returned array into an array collection.

private function result(data:Object):void{
    var someDataProvider:ArrayCollection = new ArrayCollection(data.result);
}

Fix 2

If you need ArrayCollection values within a VO, rather than doing a simple cast (well, really its an instantiation), you should create the ArrayCollection type in PHP.

class ArrayCollection{
	public $_explicitType = "flex.messaging.io.ArrayCollection";
	public $source = array();

	function ArrayCollection(){
		$this->source = array();
	}
}
?>

Then, whenever a value is expected to map to ArrayCollection within Flex, use ArrayCollection in PHP!

class SomeVO{
	public $someArray = ArrayCollection();
	...
	$someArray->source[0] = "something";
}
?>

Fix 3

This fix is very quick and easy, but don’t expect it to work ALL the time. The idea is to throw your Array into a RecordSet constructor and return that instantiation in the service call. If your call is AMF3 it will return an ArrayCollection and AMF0 will return a RecordSet.

return new RecordSet($myArray);

This works great for returning associatively indexed values ([or] results from a database query), but straight up [0,1,2] Arrays will not work.

Thanks Chad Callahan for putting this cheat sheet together!

AMFPHP, ActionScript 3, Flash Platform

April Flash Player Update breaks AMFPHP

March 26th, 2008

Updated: crossdomain.xml fixes amfphp for april flash player release

In April Adobe will release a new version of the Flash Player that now requires policy files for certain actions. If you are using AMFPHP you will need to add a crossdomain.xml file to your website to allow the sending and receiving of custom headers from flash to your server. Please make sure that you have a policy file in the document root of the web server that hosts your amfphp services on.

Here is an example crossdomain.xml policy file that will do the trick! Update the domain name to the name of the webserver that hosts your swf file.





    

    

    

    

  

Eventually I will walk through all the headers that AMFPHP needs an update this policy file and add it to the template. If you want the new player now it is included in the Flex 3 Beta SDK download. 22mb. You can get it installed and test that your application works! Update:Flash Player 9.0.124 beta allows testing against security model changes

AMFPHP, Flash Platform

Flash CS3 DataGrid with AMFPHP & MySQL

March 10th, 2008

Everyone seems to want to know what the simplest way is to populate a Flash CS3 DataGrid from AMFPHP and MySQL. This is trivial in Flex however I found that it was difficult in Flash Cs3 without a good understanding of AMFPHP. So here is the super simple example, plus a utility to help out.

First AMFPHP returns all AMF3 result resources as an ArrayCollection. This is great if you are working in Flex Builder. If you are working in Flash Cs3 AND you have not mapped your Flex library’s into Flash this is a problem.

Lets start by creating a MySQL database named products. Run the following SQL against the database to get a table Product and some data in the table. This is worth getting this database going as I am working on all the examples of remoting that mimic the BlazeDS quickstart guide!

CREATE TABLE `Product` (
  `PRODUCT_ID` int(11) NOT NULL auto_increment,
  `NAME` varchar(40) NOT NULL default '',
  `CATEGORY` varchar(40) NOT NULL default '',
  `IMAGE` varchar(40) NOT NULL default '',
  `PRICE` double NOT NULL default '0',
  `DESCRIPTION` varchar(255) NOT NULL default '',
  `QTY_IN_STOCK` int(11) NOT NULL default '0',
  PRIMARY KEY  (`PRODUCT_ID`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ;

--
-- Dumping data for table `Product`
--

INSERT INTO `Product` VALUES(1, 'Nokia 6010', '6000', 'Nokia_6010.gif', 99, 'Easy to use without sacrificing style, the Nokia 6010 phone offers functional voice communication supported by text messaging, multimedia messaging, mobile internet, games and more.', 0);
INSERT INTO `Product` VALUES(2, 'Nokia 3100 Blue', '9000', 'Nokia_3100_blue.gif', 109, 'Light up the night with a glow-in-the-dark cover - when it is charged with light you can easily find your phone in the dark. When you get a call, the Nokia 3100 phone flashes in tune with your ringing tone. And when you snap on a Nokia Xpress-on gaming co', 99);
INSERT INTO `Product` VALUES(3, 'Nokia 3100 Pink', '3000', 'Nokia_3100_pink.gif', 139, 'Light up the night with a glow-in-the-dark cover - when it is charged with light you can easily find your phone in the dark. When you get a call, the Nokia 3100 phone flashes in tune with your ringing tone. And when you snap on a Nokia Xpress-on gaming co', 30);
INSERT INTO `Product` VALUES(4, 'Nokia 3650', '3000', 'Nokia_3650.gif', 200, 'Messaging is more personal, versatile and fun with the Nokia 3650 camera phone.  Capture experiences as soon as you see them and send the photos you take to you friends and family.', 11);
INSERT INTO `Product` VALUES(5, 'Nokia 6820', '6000', 'Nokia_6820.gif', 299.99, 'Messaging just got a whole lot smarter. The Nokia 6820 messaging device puts the tools you need for rich communication - full messaging keyboard, digital camera, mobile email, MMS, SMS, and Instant Messaging - right at your fingertips, in a small, sleek d', 8);
INSERT INTO `Product` VALUES(6, 'Nokia 6670', '6000', 'Nokia_6670.gif', 319.99, 'Classic business tools meet your creative streak in the Nokia 6670 imaging smartphone. It has a Netfront Web browser with PDF support, document viewer applications for email attachments, a direct printing application, and a megapixel still camera that als', 2);
INSERT INTO `Product` VALUES(7, 'Nokia 6620', '6000', 'Nokia_6620.gif', 329.99, 'Shoot a basket. Shoot a movie. Video phones from Nokia... the perfect way to save and share life’s playful moments. Feel connected.', 10);
INSERT INTO `Product` VALUES(8, 'Nokia 3230 Silver', '3000', 'Nokia_3230_black.gif', 500, 'Get creative with the Nokia 3230 smartphone. Create your own ringing tones, print your mobile images, play multiplayer games over a wireless Bluetooth connection, and browse HTML and xHTML Web pages.', 10);
INSERT INTO `Product` VALUES(9, 'Nokia 3120', '3000', 'Nokia_3120.gif', 159.99, 'Designed for both business and pleasure, the elegant Nokia 3120 phone offers a pleasing mix of features. Enclosed within its chic, compact body, you will discover the benefits of tri-band compatibility, a color screen, MMS, XHTML browsing, cheerful screen', 10);
INSERT INTO `Product` VALUES(10, 'Nokia 3220', '3000', 'Nokia_3220.gif', 199, 'The Nokia 3220 phone is a fresh new cut on some familiar ideas - animate your MMS messages with cute characters, see the music with lights that flash in time with your ringing tone, download wallpapers and screensavers with matching color schemes for the', 20);
INSERT INTO `Product` VALUES(11, 'Nokia 6680', '6000', 'Nokia_6680.gif', 222, 'The Nokia 6680 is an imaging smartphone that', 36);
INSERT INTO `Product` VALUES(12, 'Nokia 6630', '6000', 'Nokia_6630.gif', 379, 'The Nokia 6630 imaging smartphone is a 1.3 megapixel digital imaging device (1.3 megapixel camera sensor, effective resolution 1.23 megapixels for image capture, image size 1280 x 960 pixels).', 8);
INSERT INTO `Product` VALUES(13, 'Nokia 7610 Black', '7000', 'Nokia_7610_black.gif', 450, 'The Nokia 7610 imaging phone with its sleek, compact design stands out in any crowd. Cut a cleaner profile with a megapixel camera and 4x digital zoom. Quality prints are all the proof you need of your cutting edge savvy.', 20);
INSERT INTO `Product` VALUES(14, 'Nokia 7610 White', '7000', 'Nokia_7610_white.gif', 4500, 'The Nokia 7610 imaging phone with its sleek, compact design stands out in any crowd. Cut a cleaner profile with a megapixel camera and 4x digital zoom. Quality prints are all the proof you need of your cutting edge savvy.', 7);
INSERT INTO `Product` VALUES(15, 'Nokia 6680', '6000', 'Nokia_6680.gif', 219, 'The Nokia 6680 is an imaging smartphone.', 15);
INSERT INTO `Product` VALUES(16, 'Nokia 9300', '9000', 'Nokia_9300_close.gif', 599, 'The Nokia 9300 combines popular voice communication features with important productivity applications in one well-appointed device. Now the tools you need to stay in touch and on top of schedules, email, news, and messages are conveniently at your fingert', 26);
INSERT INTO `Product` VALUES(17, 'Nokia 9500', '9000', 'Nokia_9500_close.gif', 799.99, 'Fast data connectivity with Wireless LAN. Browse the Internet in full color, on a wide, easy-to-view screen. Work with office documents not just email with attachments and memos, but presentations and databases too.', 54);
INSERT INTO `Product` VALUES(18, 'Nokia N90', '9000', 'Nokia_N90.gif', 499, 'Twist and shoot. It is a pro-photo taker. A personal video-maker. Complete with Carl Zeiss Optics for crisp, bright images you can view, edit, print and share. Meet the Nokia N90.', 12);

Here is a very simple ProductService which has two methods. The constructor that creates the DB connection and GetProducts a select * result that returns all rows. Upload the ProductService.php file into your amfphp/classes directory. Check out the service in the AMFPHP Service Browser for fun and debugging your db connection!

class ProductService {

var $dbh;

public function __construct() {

   $this->dbh = mysql_connect ("localhost", "wade", "arnold") or die ('I cannot connect to the database because: ' . mysql_error());

mysql_select_db ("product");

}

function getProducts() {

return mysql_query(sprintf("SELECT * FROM Product"));

}

}

From Flash CS3 place a DataGrid on the stage and give it an instance name of products_dg. Place a button on the stage and give it an instance name of getProducts_btn and change the label to Get Products

Create a document Main.as class and link the new fla to the class. Copy the following code into the Main.as file and update the gateway url to your AMFPHP installation.

package {

 import flash.display.MovieClip;

 import fl.events.*;

 import flash.events.*;

 import flash.net.NetConnection;

 import flash.net.Responder;

 import fl.data.DataProvider;

 import ArrayCollectionDP;

 public class Main extends MovieClip {

 	private var gateway:String = "http://localhost/amfphp/gateway.php";

 	private var connection:NetConnection;

 	private var responder:Responder;

public function Main() {

 		getProducts_btn.addEventListener(MouseEvent.CLICK, sendData);

 		responder = new Responder(onResult, onFault);

 		connection = new NetConnection;

 		connection.connect(gateway);

}

public function sendData(e:MouseEvent):void {

 		connection.call("ProductService.getProducts", responder);

 	}

 	private function onResult(result:Object):void {

 		products_dg.dataProvider = ArrayCollectionDP.toDataProvider(result);

 	}

 	private function onFault(fault:Object):void {

 		trace(String(fault.description));

 	}

}

}

Create a new ActionScript 3 file called ArrayCollectionDP.as and copy the following code into it. This class is designed to convert an AS3 ArrayCollection into a dataprovider. This is necessary until Adobe adds by default ArrayCollection to Flash Cs3. I have no idea why this class is not part of Flash but I also don’t work at Adobe.

package {

 import fl.data.DataProvider;

 public class ArrayCollectionDP {

public static function toDataProvider(myArrayCollection:Object):DataProvider {

 		var values:Array = myArrayCollection.serverInfo.initialData;

 		var category:Array = myArrayCollection.serverInfo.columnNames;

 		var aArr:Array = new Array();

 		for (var i:Number=0; i < values.length; i++) {

 			aArr[i] = new Object();

 			for (var aIndex:* in category) {

 				aArr[i][category[aIndex]] = values[i][aIndex];

 			}

 		}

 		var dp:DataProvider = new DataProvider(aArr);

 	return dp;

 	}

 }

}

This class allows you to take the ArrayCollection result from AMFPHP and pass it through the class to get a DataProvider. The datagrid’s dataprovider can now be set simply.

You end up getting something that looks like this!

You should be able to take this example and start making your application right away. The ArrayCollectionDP.as class can be reused in the future! Let me know if this helps or of course if you get stuck. I will be using this example on amfphp.org soon with more details and of course all the source files!

AMFPHP, ActionScript 3, Flash Platform

Bug in JSFL fl.findObjectInDocByType in Flash CS3

March 6th, 2008

New CS3 JSFL library’s are broken which would have been great to have. I tried to use the new finObjectInDocByType and I even used the example provided in the livedocs and it crashes. Maybe this was not implemented for AS3? I hope this gets fixed soon we could do some rad stuff! Adobe use the bug system that you have for Flex for Flash too!

******BUG******
Concise problem statement:
fl.finObjectInDocByType crashes in the example given in live docs.
Steps to reproduce bug:
Create a JSFL script and place it in your commands directory like other jsfl code.
Copy and past the first example from livedocs for finObjectInDocByType
Create a flash as3 fla file and place a text field on the stage.
command -> script name
you will get an error stating: At line 64 of file “ObjectFindAndSelect.jsfl”: TypeError: nextSymbolItemObj has no properties.

Flash Platform, jsfl

2008 Prometheus Awards

March 5th, 2008

T8DESIGN was recognized as the Iowa Software Company of the Year for company revenues under $5 million on Tuesday, March 4, 2008. T8DESIGN was the runner up behind Iowa Heath Systems for Best User of Technology.

Awards Information

 

Google Guys

Ken Patchett, operations manager at Google and the evening’s guest speaker, Chris Russell, operations manager at Google’s new 600 Million dollar Council Bluffs Data Center

Loonie

Lonnie Bloomquist, chairman of Involta, and Wade Arnold, CEO of T8DESIGN, at the Technology Association of Iowa’s 2008 Prometheus Awards where T8DSIGN was recognized as the Outstanding Software Company for a company revenues under $5 million on Tuesday, March 4, 2008 at The Meadows.

 

 

 

T8DESIGN

Flash Search SDK: maybe someday

March 3rd, 2008

Although I was very excited the Flex Search SDK does not seem to be very useful and does not support flash player 9. Unfortunately It just supports what is presented on frame 1.This leads a lot to be desired if you use deep linking in your flash based website.  My hope was to have a tool that I could execute on the currently loaded state of the SWF. A module that could be integrated with the webserver so that the state of the SWF would have changed you could execute the swf2html and create an HTML page of that state. Alas I will continue using swfaddress.com to do SEO. Maybe more fun in the future from adobe!

ActionScript 3, Flash Platform

BlazeDS: Worth figuring out! HelloWorld Example

March 2nd, 2008

I am working on a project for John Deere and they have a huge WebSphere implementation. The odds of transferring them over to AMFPHP are not very realistic! Anyways, I spent the weekend playing with BlazeDS as my endpoint for Flex and I really like it. I took me about six hours to figure out tomcat, java in eclipse, and the whole server side endpoint thing. From there it has only taken me about an hour to figure out class mapping, authentication, push technology, and connecting everything to hybernate. So to anyone looking into using BlazeDS stick with it a bit. The biggest hurdle is probably java and tomcat for those like me that don’t understand why you need to restart the application server sometimes and other times it just works. Overall great job Adobe and thanks for releasing a quality opensource project.

The following is my simple hello world example that I used to get started with learning how this system works.

Here are all the files Zipped. I can not figure out how to do code highlighting. Suggestions~!

helloworld-blazeds.zip

Java Class File for remote service. Place compiled class in $tomcat_home/webapps/blazeds/WEB-INF/classes/HelloWorld.class

import java.util.Date;
public class HelloWorld {
	private String userSaid;
	public String repeat(String said) {
		this.userSaid = "Reply from server: " + said;
		return this.userSaid;
	}
	public String sayHello() {
		Date now = new Date();
		return "Hello World " + now;
	}
}

Remoting-config.xml place in $tomcat_home/webapps/blazeds/WEB-INF/flex/remoting-config.xml


    
        
    
    

   			HelloWorld
   		
   
    
        
    

services-config.xml $tomcat_home/webapps/blazeds/WEB-INF/flex/services-config.xml


	
		
			
	        	
	    	
	    	

	            	HelloWorld
		        
		        
					
				
	    	
    	
	
	
		
			
		
	

That’s it for the server side. Now you just need two files updated to run this from Flex.



    
        
        
    

    
        
    

    
    
    
    
    

And then your services-config.xml file in your flex project. Note that this can be the same file as what is on the server! But it needs to be in both places.



    class="flex.messaging.services.RemotingService">

    
        
    
    

   			HelloWorld
   		
   
    
        
    


That’s it! Now you have your first class connecting against BlazeDS!

ActionScript 3, Blaze DS, Flash Platform