ActionScript
Loading Facebook Profile Picture Into Flash SWF Using Graph API
December 8, 2010
14

The guide below is an extension of this tutorial:
http://www.permadi.com/blog/2010/12/using-facebook-open-graph-api-in-flash-as3/.

The function to get your profile picture is

Facebook.getImageUrl(uid);

Where uid is the Facebook user id.

Once you establish a Facebook connection, your user id is available at Facebook.getSession().uid. So we can call:

Facebook.getImageUrl(Facebook.getSession().uid);

This will give you the URL which ‘theoretically’ you can ask a Loader object to load the picture. But, are you tired of getting this error when loading a picture (such as your profile picture) into a swf?

SecurityError: Error #2122: Security sandbox violation:
Loader.content: http://yourdomain/your.swf
cannot access http://static.ak.fbcdn.net/rsrc.php/zo/r/UlIqmHJn-SK.gif?path=https%3A%2F%2Fgraph%2Efacebook%2Ecom%2F100001729250263%2Fpicture.
A policy file is required, but the checkPolicyFile flag was not set when this media was loaded.

In the old API, you can solve this by loading the crossdomain.xml file manually

Security.loadPolicyFile("http://profile.ak.fbcdn.net/crossdomain.xml");

Or by assigning LoaderContext and tell it to load the policy file.

	var loaderContext: LoaderContext = new LoaderContext();
	loaderContext.checkPolicyFile = true;
	loaderContext.securityDomain=SecurityDomain.currentDomain;

None of them works with http://static.ak.fbcdn.net/ because it turns out that the crossdomain.xml in http://static.ak.fbcdn.net/ looks like this (December 2, 2010):

<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="s-static.facebook.com"/>
<allow-access-from domain="static.facebook.com"/>
<allow-access-from domain="static.api.ak.facebook.com"/>
<allow-access-from domain="*.static.ak.facebook.com"/>
<allow-access-from domain="s-static.thefacebook.com"/>
<allow-access-from domain="static.thefacebook.com"/>
<allow-access-from domain="static.api.ak.thefacebook.com"/>
<allow-access-from domain="*.static.ak.thefacebook.com"/>
<allow-access-from domain="*.static.ak.fbcdn.com"/>
<allow-access-from domain="external.ak.fbcdn.com"/>
<allow-access-from domain="*.static.ak.fbcdn.net"/>
<allow-access-from domain="external.ak.fbcdn.net"/>
<allow-access-from domain="www.facebook.com"/>
<allow-access-from domain="www.new.facebook.com"/>
<allow-access-from domain="register.facebook.com"/>
<allow-access-from domain="login.facebook.com"/>
<allow-access-from domain="ssl.facebook.com"/>
<allow-access-from domain="secure.facebook.com"/>
<allow-access-from domain="ssl.new.facebook.com"/>
<allow-access-from domain="static.ak.fbcdn.net"/>
<allow-access-from domain="fvr.facebook.com"/>
<allow-access-from domain="s-static.ak.facebook.com"/>
<allow-access-from domain="www.latest.facebook.com"/>
<allow-access-from domain="www.inyour.facebook.com"/>
<allow-access-from domain="s-static.ak.fbcdn.net"/>
</cross-domain-policy>

It doesn’t look like the policy allows external domains, that’s why you get the exception.

As a side note, here’s how the crossdomain.xml should looks like (from
http://profile.ak.fbcdn.net/crossdomain.xml , if you have used the OLD Rest API you might recognize this URL):
<cross-domain-policy>
<allow-access-from domain="*"/>
<site-control permitted-cross-domain-policies="master-only"/>
</cross-domain-policy>
</pre>

Rather than relying on the cross-domain, the more reliable solution is to write a proxy loader on your own server which loads the image for you. Here’s an example using PHP that loads the actual image then sends is to the SWF.

<?php
$path=$_GET['path'];
if (stristr($path, "fbcdn.")==FALSE && stristr($path, "facebook.")==FALSE)
{
  echo "ERROR";
  exit;
}
header("Content-Description: Facebook Proxied File");
header("Content-Type: image");
header("Content-Disposition: attachment; filename=".$path);
@readfile($path);
?>

I saved the code above as facebookProxy.php and when I am loading an image from Facebook, I pass the URL of the image in path variable.
And then below I added the code to load the picture, by calling facebookProxy.php passing the path of the image in the URLVariables. Note: The code below is an extension of this tutorial:
http://www.permadi.com/blog/2010/12/using-facebook-open-graph-api-in-flash-as3/.
The code also checks to make sure path is either “facebook” or “fbcdn.” Note: This is a bare-bone example. Reading, writing and prinitng files is a risky operations and a real application should add more security measures to prevent security breaches.

function loadMyPicture():void
{
  var loader:Loader = new Loader();
  loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMyPictureLoaded, false, 0, true);

  var request:URLRequest = new URLRequest("facebookProxy.php");
  var variables:URLVariables = new URLVariables();
  variables.path = Facebook.getImageUrl(Facebook.getSession().uid);
  request.data = variables;

  loader.load(request);

}

function onMyPictureLoaded(event:Event):void
{
  var loader:Loader=event.target.loader;
  loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onMyPictureLoaded);
  loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onMyPictureLoadError);
  var bitmap = Bitmap(loader.content);
  bitmap.smoothing=true;

  //Note: picturePlaceholder is just a blank movie clip on the Stage
  bitmap.width=picturePlaceholder.width;
  bitmap.height=picturePlaceholder.height;
  picturePlaceholder.addChild(bitmap);
}

The example can be accessed here in a stand alone state:
http://www.permadi.com/tutorial/as3-open-graph-example/?login.

You can use a similar method to load friend’s profile picture. Here’s an example of a game that uses your friend’s pictures: http://apps.facebook.com/jigsaw-friends/ (you account must have several friends in order to see your friend photos).