Getting list of Facebook friends from a test account

To get the list of friends of a specific user, you are supposed to issue a simple GETrequest to me/friends (or USER_ID/friends), passing the user accessToken in the request.

Facebook used to return an array named data where each value is an object representing a friend. Each of this objects had two keys : idand name.

Until yesterday, it worked well.

Today, it seems broken for test users. The namekey is no longer returned in the call, you only get id.

I'm not sure it's intentionnal or not. At least I haven't seen any notice about this change. But I'm not sure it's a bug either, as Facebook documentation is crappy, we never really know if the output we got is the expected one or if it's a bug.

I'm not even sure we were supposed to get the namein the first place, actually.

What is definitely a bug is that the behavior is different for test users that for classic users.

Passing flashVars with Flash 10 in IE

I've spent the last two days debugging a weird issue involving https, IE and Flash.

In the end, I boiled the issue down to IE and Flash 10, https wasn't involved (in fact, that was a different issue).

Markup hell

It is known that to have a real crossbrowser markup to embed Flash we need an IE specific version and a non-IE one.

What I didn't know was that flashvarsneeded to be passed in two different formats between Flash player 10 and Flash player 11.

11 expect the classic flashvarsparameter while 10 expect them to be passed as simili GET parameters to the movie url.

Final HTML markup

In the end, here is the PHP code I use to generate my SWF markup :

sprintf(
  '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="%1$s" height="%2$s" id="%3$s">
    <param name="movie" value="%4$s?%6$s" />
    %5$s
    <!--[if !IE]>-->
      <object type="application/x-shockwave-flash" data="%4$s" width="%1$s" height="%2$s">
      %5$s
    <!--<![endif]-->
    %7$s
    <!--[if !IE]>--></object><!--<![endif]-->
  </object>
',
$width, $height, $id, $url, $params, $flashVars, $alternateContent);

Where :

  • $width and $height are the size (in pixel) of your movie
  • $id is the html/css id of the main object element (as used in swfObject.getObjectById)
  • $url is the url address of your swf file
  • $params is a string containing all the <param name="name" value="value" /> that you want to pass. Usually it will contain the wmode, allowfullscreen, allowscriptaccessand flashvarskeys.
  • $flashVars is a duplicate of the flashVarskey of $params and should contain a string in the form foo=bar&baz=nyan to be passed to the swf in Flash 10
  • $alternateContent is the html text to be displayed when Flash is not installed in the browse

I hope that this markup will help you, because I spent a damn long time testing all that stuff, jungling between VM and IE instances.

swfobject.getObjectById() when flash not installed

SWFObject is the de-facto library used whenever you need to ember Flash files in your code. It takes care of smoothing all cross browser issues.

It has a getFlashPlayerVersionmethod that return a string of the current version in the form major.minor.release. Its value is 0.0.0 if Flash isn't installed.

It also provides a cross browser markup, including conditionnal comments for IE, that validate and works everywhere. The downside is that it forces you to create two elements in your markup with the same id.

Hopefully, the getObjectByIdmethod is here to return the correct DOM element based on the browser flash integration type.

But... It seems that the mechanisme is buggy when Flash isn't installed (on 2.2)

I've tested running IE9 without Flash installed and FF8 with Flash disabled, and the return of getObjectByIddiffers : I got nullin IE9 and the DOM element in FF8.

I've added a small patch to my code to take it into account :

var el = swfobject.getObjectById(id) || document.getElementById(id);

And I've also submitted a bug report.

Fix the floating issue with json_decode in PHP 5.3

When dealing with online API that are handling a lot of items (like Twitter or Facebook), you'd better be aware of a PHP limitation with json_decode.

json_decode is supposed to take a JSON string and return a PHP array or a PHP object from it.

Unfortunatly if one of the key is an int and is bigger than the max int value, it will be cast as float instead. And you'll lose precision in the process.

In my case it resulted in a complete unability to find a user in the database as the id didn't match anything. This was quite hard to find as I couldn't reproduce it on my local machine.

Know your system

My local system was a 64bits machine while the production servers were 32bits. And of course, max int precision is far bigger on 64bits machines so the error didn't pop in my tests.

If you're running PHP 5.4, the fix is easy. Just add the JSON_BIGINT_AS_STRING bitmask as 4th option like this

$decoded = json_decode($encoded, true, null, JSON_BIGINT_AS_STRING);

If you're running a 32bits machine with PHP 5.3 like me, it's a little more tricky.

The regexp

My solution is to parse the original JSON string and add quotes around ints so json_decode will keep them as string.

My first attempt was naive

preg_replace('/":([0-9]+),/', '":$1,', $encoded)

This will find any int between ": (marking the end of a key) and , (marking the start of the next key), and replace it with the same string but enclosed in quotes.

I soon found out that this did not cover all the cases, especially if the int key was the last of the JSON, it won't be followed by a , but by a } instead.

So, I adapted it a little bit :

preg_replace('/":([0-9]+)(,|})/', '":"$1"$2', $encoded)

Ok, it worked better. Any int key in the JSON, anywhere will be enclosed in quotes.

It was a little overkill so I decided to limit it to keys of at least 10 digits

preg_replace('/":([0-9]{10,})(,|})/', '":"$1"$2', $encoded)

Better. But still not perfect.

As I soon discovered, sometimes Facebook returned JSON containing JSON itself (in Request dataor Credit order_info for example).

The previous approach would add quotes around ints in JSON escaped string and would thus corrupt the whole key.

This time, I added a final touch. I only added quotes around int that were not in an escaped JSON string themselves, by checking that the closing quote of the key wasn't escaped.

preg_replace('/([^\\\])":([0-9]{10,})(,|})/', '$1":"$2"$3', $encoded)

Here it is, the final fix. I might have forgotten some corner cases, but at least it works for my current application.

Hope it helps !

Accessing a frame with Firebug console

If you want to access the Javascript console of an inner frame of a webpage, know that you can "browse" through the window as you could browse through a file system.

For example, if you want Firebug to use the first frameof the page as its current window object, just type the following code in Firebug console :

cd(window.frames[0])

This proved immensely useful when debugging a Facebook application.