views:

323

answers:

4

My JavaScript application uses Facebook Connect to display the profile pictures of a user's friends.

This worked fine until a recent update on Facebook's end created a bug in Safari.

Essentially, everything works fine unless a user's friend has an apostrophe (single quote) in their name. Think Irish last names like O'Connor, for example. An apostrophe completely breaks the rendering of all profile pictures, and only silhouettes are displayed instead.

Usually when rendering the fb:profile-pics, the friend's name becomes the value of the image's alt and title attributes. However, with a name with an apostrophe, this happens instead (using the name Gregory O'Connor for this example):

<fb:profile-pic class=" FB_profile_pic_rendered FB_ElementReady">
  <!-- Notice the strange new "connor" attribute -->
  <img class=" FB_profile_pic fb_profile_pic_rendered " style="" connor="" title="Gregory O" alt="Gregory O" src="http://profile.ak.fbcdn.net/path/to/friends/profile/image.jpg"&gt;
<fb:profile-pic>

Luckily for me, my code is almost identical to the code Facebook gives for an example of the FB.ApiClient.friends_get function, which can be found here (and will reproduce the Safari bug if a friend has an apostrophe in their name).

From: http://developers.facebook.com/docs/?u=facebook.jslib.FB.ApiClient.friends_get

 <div id="profile_pics"></div>
 <script type="text/javascript">
   var widget_div = document.getElementById("profile_pics");
   FB.ensureInit(function () {
     FB.Facebook.apiClient.friends_get(null, function(result) {
       var markup = "";
       var num_friends = result ? Math.min(10, result.length) : 0;
       if (num_friends > 0) {
         for (var i=0; i<num_friends; i++) {
           markup +=
             '<fb:profile-pic size="square" uid="'
             + result[i]
             + '" facebook-logo="true">'
             + ' </fb:profile-pic>';
          }
        }
        widget_div.innerHTML = markup;
        FB.XFBML.Host.parseDomElement(widget_div);
      });
    });
  </script>

Since Facebook has been silent on this bug, I need to come up with a fix on our end. I started trying to strip out apostrophes (which got ugly pretty fast due to the layers of communication and abstraction between Facebook and our application), and decided I should step back and ask for advice on how to solve this problem here.

Many thanks in advance.

Edit

I'd like to clarify by giving a real-world example of HTML generated by the call to Facebook. Essentially, the above JavaScript will grab the user ID from the call to result above, and from that result generate HTML for the image.

I believe escaping the result from img alt and img title will fix this bug, but the question of how to get access to it still exists for me.

Example:

<fb:profile-pic class=" FB_profile_pic fb_profile_pic_rendered FB_ElementReady" facebook-logo="false" linked="false" uid="6841956" size="normal">
  <img class=" FB_profile_pic fb_profile_pic_rendered" style="opacity: 1;" connor="" title="Colin O" alt="Colin O" src="http://profile.ak.fbcdn.net/v227/676/36/n6841956_271.jpg"&gt;
 </fb:profile-pic>

Thanks again!

A: 

I'm wondering if

...
 markup +=
   '<fb:profile-pic size="square" uid="'
         + escape(result[i])
         + '" facebook-logo="true">'
         + ' </fb:profile-pic>';
...

would work?

F3
I hoped it would, too. It doesn't, unfortunately. I think maybe if I could explicitly escape the img alt and title returned by Facebook I might have better luck, but I'm not sure of the best way to do that...
Bryan Woods
A: 

Try something like

markup +=
   '<fb:profile-pic size="square" uid="' +
       result[i].replace(/'/g, "&apos;").
           replace(/"/g, "&quot;").
           replace(/\</g, "&lt;").
           replace(/\>/g, "&gt;") +
       '" facebook-logo="true">' +
       '</fb:profile-pic>';

After all, if it's XML, it might as well be valid XML, right? :-)

Anthony Mills
A: 

Do you have an updated URL for the API call? The one listed in the question appears to reference the FB JavaScript API, but I didn't see any analogous friends_get function.

What exactly does result[i] contain after calling that JS function? The markup code you list suggests that result[i] only appears in the element. Where does the tag in your resultant HTML get generated from (which has the title and alt attributes of interest)?

markup += '<fb:profile-pic size="square" uid="'
    + result[i]
    + '" facebook-logo="true">'
    + ' </fb:profile-pic>';
Robert Hui
+1  A: 

Related to the answer by F3, but rather than attempting to encode the entire result (see the following link for differences: http://xkr.us/articles/javascript/encode-compare/) can you not just encode (or remove) the single quotes?

result[i].replace(/'/g,"%27")

Alternately, this regex pattern should match all instances of the ' character

"/'[^']*+'/"

Like Robert, if you could provide an example of what is returned it would help a bunch.

iivel