I am using the latest update of Drupal for Facebook. I have a custom node with few fields that is rendered using a custom template. For instance the node contains an image field which is linked to the node. When the user clicks on it, it goes to a page which shows the node contents. Inside the node template the image field is rendered using: print render($content['field_tags']); so there is no magic to render the image. until recently (prior to the recent update forced by Facebook changes, arghhh!!) the template and link used to be re-written correctly to a canvas url. But now the link is an absolute link to the main Website. I have not made changes to my application. On the canvas page settings in Drupal I have " Replace absolute hrefs, not just relative, with canvas page URLs." on. So, I assume it should rewrite the absolute URLs. But it does not. Are there any settings that I am missing to make this work or it is a bug?

Comments

nvd_ai61’s picture

after some effort I figured out that the URLs that are not re-written are those that are alias, e.g., instead of .../node/15 the url is .../content/mynewcontent. After removing the alias it works fine. Moreover, I was using pathauto module that was automatically generating alias for several contents. I disabled it and now all the newly generated contents won't use alias and their URL are re-written perfectly.

Now it makes me wonder, what other options do I have besides disabling all the aliases? is this a missing functionality from Drupal for Facebook to also re-write the URLs generated by aliases?

Dave Cohen’s picture

Try updating to latest .dev build because I believe I fixed something about this. It certainly should work properly with aliases, if not it is a bug.

nvd_ai61’s picture

Hi Dave,

I am already on the latest .dev build from Oct-02 and have this issue. The only thing that may be relevant is that I am still on Drupal 7.2. Do you think this may cause the bug?

Dave Cohen’s picture

Probably a bug in fb_url_rewrite.inc. This stuff has changed so much between drupal 6 and 7. I don't know what the bug is but I expect it is in there.

jack_tux’s picture

Priority: Normal » Major

This bug is still there in the lastest dev.

Has anyone had a fix for this yet??

Dave Cohen’s picture

the image field is rendered using: print render($content['field_tags']); so there is no magic to render the image.

Looks like is could be magical.

Does the field ever call url() or l() to create the link?

This might be a worthwhile investigation...

1) put return $output at the top of fb_process(), so it doesn't change anything.

2) view source of a page with this problem.

3) view source of a page without this problem. nvd_ai61 reports that when the url alias is not used, the problem does not occur.

4) what are the two URLs now? Does one have /fb_cb/.../ inserted into it, and the other does not?

Alex Savin’s picture

I'm also having this problem. Mine it goes even further. I get an HTTP 500 status after being sent to _TOP.

I'm also using the latest dev (7.x-3.x-dev from Nov-10)

Alex Savin’s picture

After deactivated URL language switching method, the rewrite of URLs works again. Is this happening only to me or is it a general rule that if you have a language prefix in the URL canvas the links wont work? As I said before that I got only HTTP 500 responses. BTW nvd_ai61, is your site multilingual?

Dave Cohen’s picture

There's at least one other issue in the queue about problems with i18n. I'm hoping the community can come up with a patch for those problems. I believe the i18n handling changed in D7, and it's pretty delicate and I personally don't have any canvas apps trying to use it.

So thanks for reporting that the issue is i18n related (for you, I'm not sure about the others on this thread). If you can fix it, please post a patch!

scott shipman’s picture

I am finding that views that display my custom content type are not re-writing. A view of taxonomies (vocabulary) is also not rewriting. Not sure if its the views or the pathauto though.

What tests can I do to help debug this?

Running:
Pathauto 7.x.1.0 - prefer to have url path auto-generated because its user generated content, using taxonomies
Views 7.x.3.0 with image field, linked to content
Drupal 7.1
DPF 7.x.3.x

https://apps.facebook.com/deedfulthings/

jack_tux’s picture

Has anyone been able to fix this?

With URL Alias turned on the theme changes back to the system default after clicking the first link.

jddeli’s picture

Has anyone been able to fix this?

Alex Savin’s picture

I manage to fix this by implementing a new language negotiation method. It basically takes the language from the signed request.

This is the code:

/**
 * Implements hook_language_negotiation_info().
 */
function module_name_language_negotiation_info() {
  return array(
    'facebook_locale' => array(
      'types' => array(LANGUAGE_TYPE_INTERFACE),
      'callbacks' => array(
        'language' => 'module_name_facebook_get_lang'
      ),
      'weight' => 0,
      'name' => t('Facebook locale'),
      'description' => t('Facebook locale set by the user in canvas applications.'),
      'cache' => 0,
      'file' => drupal_get_path('module', 'module_name') . '/module_name.module'
    )
  );
}

/**
 * Helper function that finds the language that the user uses in Facebook
 * @global type $language
 * @param type $langs
 * @return type
 */
function module_name_get_lang($langs) {
  if (isset($_REQUEST['signed_request'])) {
    global $language;
    $sr = module_name_parse_signed_request($_REQUEST['signed_request']);

    $locale = preg_replace('/_[A-Z]{2}/', '', $sr['user']['locale']);
    // check that our desired language exists
    if (array_key_exists($locale, $langs)) {
      // override language to use our preferred language
      $_SESSION['fb_locale'] = $locale;
      return $locale;
    }
  }
  else if ($_SESSION['locale']) {
    return $_SESSION['locale'];
  }
  else {
    return FALSE;
  }
}

/**
 * Helper function to parse the signed request posted by Facebook.
 * We can't use the SDK at this point because it is to early in the execution process (used only in language negotion)
 * @param string $signed_request
 * @return array The parsed signed request.
 */
function module_name_parse_signed_request($signed_request) {
  global $config;
  $secret = $config['fb_secret'];
  list($encoded_sig, $payload) = explode('.', $signed_request, 2);

  // decode the data
  $sig = base64_decode(strtr($encoded_sig, '-_', '+/'));
  $data = json_decode(base64_decode(strtr($payload, '-_', '+/')), true);

  if (strtoupper($data['algorithm']) !== 'HMAC-SHA256') {
    watchdog(ZOOBE_WATCHDOG, 'Unknown algorithm. Expected HMAC-SHA256');
    return null;
  }

  // check sig
  // we are using the secret from sett in the settings.php because is too early to have it from fb module
    $expected_sig = hash_hmac('sha256', $payload, $secret, $raw = true);
    if ($sig !== $expected_sig) {
      error_log('Bad Signed JSON signature!');
      return null;
    }

  return $data;
}

You have to replace module_name with the actual name of your module and sett $config['fb_secret'] in your settings.php file. Now you can go to language settings menu and set this as the first negotiation method.

Dave Cohen’s picture

Issue tags: +fb, +fb canvas

That's cool. There's some code in fb_settings.inc that could be changed to save your module the trouble of parsing the signed request.

This is definately a candidate for a patch to fb.module to implement the language negotiation hooks.

Alex Savin’s picture

If I'm not wrong, you're referring to _fb_settings_parse_signed_request(), aren't you? This doesn't validate the sg but anyway I don't think is really necessary to check it at this point.
I'll try today or tomorrow to build a patch for this if you're not doing it already.

Dave Cohen’s picture

I'm not working on it already. By all means please do make a patch.

Don't call _fb_settings_parse_signed_request() directly. As you point out it does not validate, but it doesn't do anything so critical that it really needs it. (The signed request is validated later by the facebook PHP SDK, its just that we haven't loaded that yet, and don't want to yet).

Instead of calling that, patch _fb_settings_honor_signed_request() so that it adds the locale info to fb_settings(). I.e., a new constant FB_SETTINGS_USER_LOCALE or some such. So that fb_get_lang() would contain a check like if ($lang = fb_settings(FB_SETTINGS_USER_LOCALE)) { ... }. I think that's how I'd do it, the fewer places the code has to know the structure of the signed request, the better.

Alex Savin’s picture

I think is ready. Please someone test it because I could only test it against a previous dev release.

Alex Savin’s picture

Status: Active » Needs review
StatusFileSize
new2.52 KB

... and the patch :)

Dave Cohen’s picture

Status: Needs review » Needs work
StatusFileSize
new2.51 KB

I'm not sure I fully understand this langauge stuff, I don't have a multi-langauge site set up right now to see it in action. But there are already some options under admin >> structure >> fb apps >> settings where locales are mapped to langauges. Shouldn't this new piece also use that mapping? Is it safe to just return the facebook language code without checking the $langs passed into fb_get_lang()??

I tweaked the patch a little, attached.

Alex Savin’s picture

I was checking it in my initial code but I took a look into the function that retrieves the result of the callback and it also checks to see if the returned language is real and enabled.

What this piece of code does is implementing a new language switcher that dynamically switches the language based on the current facebook session locale that can be changed from the footer page of facebook (or recently I saw it on the bottom right side). The problem with dff and languages is that, because dff adds the path prefix, multilingual sites are broken while in canvas. The path prefix should not be used by third party modules because it's only purpose is to be used with switching the language by url prefix.

'prefix': Only used internally, to modify the path when a language dependent URL requires so.

This patch is quite critical for multilingual web sites that are using dff module.

Dave Cohen’s picture

Right, I agree with the goal of the patch. You sound convinced the $langs array should be ignored. There's already a setting that maps facebook locales to drupal languages - I didn't write that, it was submitted by another user with a multi-langauge site.

I just noticed in reviewing the patch that (with patch applied) there are these two pieces that have to do with language, but have nothing to do with each other. I strongly suspect they should work together instead of separately.

And while your patch has more to do with canvas pages, it's possible to learn the user's locale even in a facebook connect scenario. I feel like this code is likely to do that as well, in the not too distant future.

Alex Savin’s picture

Would't it be a good idea to have a hook from which dff learns the language. And it can be implemented in fb_canvas or fb_connect or any other 3rd party module? The hook should be triggered in fb_settings.inc where the vars are sett.

Dave Cohen’s picture

I don't see the advantage of a hook. And I certainly don't want fb_canvas and fb_connect to both be concerned with language/locale. I want only one small chunck of code to maintain. And as long as Drupal knows the right language, that should be enough. Right?

Alex Savin’s picture

I thought that those modules (or such modules) might better know information like this which is related to functionality specific to them. But you know better this module and can better make a decision regarding this.

Alex Savin’s picture

StatusFileSize
new5.77 KB

Updated the patch to work against beta3