? facebook-platform
? themes/ep_fbml
Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/README.txt,v
retrieving revision 1.16
diff -u -p -r1.16 README.txt
--- README.txt	5 Feb 2009 02:47:28 -0000	1.16
+++ README.txt	22 Feb 2009 20:13:03 -0000
@@ -5,7 +5,7 @@ More information: http://www.drupalforfa
 
 Primary author and maintainer: Dave Cohen (http://www.dave-cohen.com/contact)
 
-Version: HEAD (version 2.x for Drupal 5.x)
+Version: N/A (version 2.x for Drupal 6.x)
 Please read http://drupal.org/node/288721#version and confirm that
 you are using the correct version.
 
Index: fb.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb.info
--- fb.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb.info	22 Feb 2009 20:13:03 -0000
@@ -1,3 +1,5 @@
 name = DFF Facebook API
 description = Imports and uses the Facebook API.
 package = Drupal for Facebook
+core = 6.x
+php = 5
Index: fb.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb.install,v
retrieving revision 1.2
diff -u -p -r1.2 fb.install
--- fb.install	7 Apr 2008 20:56:49 -0000	1.2
+++ fb.install	22 Feb 2009 20:13:03 -0000
@@ -7,18 +7,8 @@ function _fb_install_set_weight() {
 function fb_install() {
   _fb_install_set_weight();
 }
-function fb_update_1() {
-  _fb_install_set_weight();  
-}
 
-/**
- * The callback URL has changed and this requires manual updates to App settings.
- */
-function fb_update_2() {
-  $message = t('Warning!  The Drupal for Facebook modules have changed.  Manual intervention is required!  See !url1 or !url2.',
-               array('!url1' => l('http://apps.facebook.com/drupalforfacebook/node/1055', 'http://apps.facebook.com/drupalforfacebook/node/1055'),
-                     '!url2' => l('http://drupalforfacebook.org/node/1055','http://drupalforfacebook.org/node/1055')));
-  drupal_set_message($message);
-  watchdog('fb', $message);
+function fb_uninstall() {
+  _fb_install_set_weight();
 }
-?>
\ No newline at end of file
+
Index: fb.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb.module,v
retrieving revision 1.40
diff -u -p -r1.40 fb.module
--- fb.module	5 Feb 2009 02:47:28 -0000	1.40
+++ fb.module	22 Feb 2009 20:13:03 -0000
@@ -67,7 +67,7 @@ function fb_init() {
 	  if (strpos($key, 'fb_') === 0)
 	    $req[] = $key . '=' . $val;
 	}
-	$url = url($_REQUEST['q'], implode('&', $req), NULL, TRUE);
+        $url = url($_REQUEST['q'], array('query' => $req, 'absolute' => TRUE));
 	if (fb_verbose())
 	  watchdog('fb_debug', t('Facebook session key was %old, now %new.  Destroying session and sending user to %url.',
 				 array('%old' => $_SESSION['fb_frame_params']['session_key'],
@@ -93,7 +93,7 @@ function fb_init() {
                          array('!drupal_for_facebook' => l(t('Drupal for Facebook'), 'http://drupal.org/project/fb'),
                                // This link should work with clean URLs
                                // disabled.
-                               '!readme' => '<a href='.base_path() . '/' . drupal_get_path('module', 'fb') . '/README.txt>README.txt</a>')), 'error');
+                               '!readme' => '<a href='. base_path() . drupal_get_path('module', 'fb') .'/README.txt>README.txt</a>')), 'error');
   }
   
   // Ask other modules for app detail
@@ -186,18 +186,21 @@ function fb_api_init($fb_app, $fbu) {
   $fbu_orig = $fbu;
   
   // Determine the actual facebook user id to use.
-  if ($GLOBALS['fb'] && $GLOBALS['fb']->validate_fb_params() &&
+  if ($GLOBALS['fb'] && $GLOBALS['fb']->api_key == $fb_app->apikey && 
+      $GLOBALS['fb']->validate_fb_params() &&
       ($fbu == FB_FBU_CURRENT || $fbu == FB_FBU_ANY ||
        $fbu == $GLOBALS['fb']->get_loggedin_user())) {
     return $GLOBALS['fb'];
   }
-  else if (($fbu == FB_FBU_CURRENT || $fbu == FB_FBU_ANY) 
+  else if ($GLOBALS['fb']->api_key == $fb_app->apikey && 
+           ($fbu == FB_FBU_CURRENT || $fbu == FB_FBU_ANY) 
            && isset($_SESSION['fb_frame_params']) && !$_REQUEST['fb_sig']) {
     $params = $_SESSION['fb_frame_params'];
     $fbu = $params['user'];
     $session = $params['session_key'];
   }
-  else if ($fbu == FB_FBU_CURRENT && $GLOBALS['fb']) {
+  else if ($GLOBALS['fb'] && $GLOBALS['fb']->api_key == $fb_app->apikey &&
+           $fbu == FB_FBU_CURRENT) {
     // No current user to use, probably anonymous canvas page.
     return $GLOBALS['fb'];
   }
@@ -258,9 +261,9 @@ function fb_api_init($fb_app, $fbu) {
     if ($fbu_orig != FB_FBU_NO_SESSION &&
 	$fbu_orig != FB_FBU_CURRENT && !$fb->get_loggedin_user()) {
       // An FBU other than CURRENT was specified, but we failed to log in.
-      watchdog('fb', t('Failed to log into facebook app %app as user %user',
-                       array('%app' => $fb_app->title,
-                             '%user' => $fbu_orig)), WATCHDOG_ERROR);
+      watchdog('fb', 'Failed to log into facebook app %app as user %user',
+               array('%app' => $fb_app->title,
+                     '%user' => $fbu_orig), WATCHDOG_ERROR);
     }
   }
   
@@ -315,6 +318,18 @@ function fb_facebook_user($fb = NULL) {
 }
 
 /**
+ * Facebook provides a method, users_isAppUser(), which is buggy and
+ * unreliable.  So we need to implement our own.
+ */
+function fb_is_app_user($fb) {
+  if ($fb->api_client->added || $fb->api_client->is_user)
+    return TRUE;
+  else
+    return $fb->api_client->users_isAppUser;
+}
+
+
+/**
  * Given a local user id, find the facebook id.
  */
 function fb_get_fbu($uid, $fb_app = NULL) {
@@ -342,7 +357,7 @@ function fb_get_fbu($uid, $fb_app = NULL
  * TODO: This code will probably not handle every case and may need some work.
  */
 function fb_get_callback_url($fb_app) {
-  $url = url('', NULL, NULL, TRUE) . FB_SETTINGS_APP_NID . '/'. $fb_app->nid . '/';
+  $url = url('', array('absolute' => TRUE)) . FB_SETTINGS_APP_NID . '/'. $fb_app->nid . '/';
   return $url;
 }
 
@@ -362,7 +377,7 @@ function fb_get_app($search_data) {
  * Convenience method to return a list of all known apps, suitable for form
  * elements.
  */
-function fb_get_app_options($include_current) {
+function fb_get_app_options($include_current = FALSE) {
   $apps = fb_get_all_apps();
   $options = array();
   if ($include_current)
@@ -471,15 +486,15 @@ function fb_user_load($fbu = NULL) {
     if (!$account)
       $account = user_load(array('uid' => variable_get('fb_facebook_user', 2)));
     if (!$account)
-      watchdog('fb', t('Failed to load user from facebook fbu=%fbu',
-                       array('%fbu' => $fbu)), 'error');
+      watchdog('fb', 'Failed to load user from facebook fbu=%fbu',
+                       array('%fbu' => $fbu), 'error');
     $account->fbu = $fbu;
     return $account;
   }
 }
 
 
-function fb_form_alter($form_id, &$form) {
+function fb_form_alter(&$form, &$form_state, $form_id) {
   // Because facebook users don't have email, it can't be required on user form
   if ($form_id == 'user_register') {
     if (user_access('administer users')) {
@@ -494,26 +509,21 @@ function fb_form_alter($form_id, &$form)
 }
 
 
-function fb_menu($may_cache) {
+function fb_menu() {
   $items = array();
   
-  if (!$may_cache) {
-    // Initialization moved to fb_init(), nothing to do here.
-  }
-  else {
     // When forms are submitted directly to us, we cache the results,
     // and show them later via this callback
-    $items[] = array('path' => 'fb/form_cache',
-                     'callback' => '_fb_form_cache_cb',
+    $items['fb/form_cache'] = array(
+                     'page callback' => '_fb_form_cache_cb',
                      'type' => MENU_CALLBACK,
-                     'access' => TRUE);
+                     'access callback' => TRUE);
 
     // A page to help determine infinite session keys
-    $items[] = array('path' => 'fb/session',
-                     'callback' => '_fb_session_cb',
+    $items['fb/session'] = array(
+                     'page callback' => '_fb_session_cb',
                      'type' => MENU_CALLBACK,
-                     'access' => TRUE); // TODO: restrict access?
-  }
+                     'access callback' => TRUE); // TODO: restrict access?
   return $items;
 }
 
@@ -753,14 +763,14 @@ function fb_add_js($filename, $type) {
   static $cache;
   if (!$cache) {
     $cache = array();
-
+    
     // Add the most basic file we need.
     $base_file = drupal_get_path('module', 'fb') . '/fb_fbml.js';
     $base_file .= "?v=".filemtime($base_file);
     drupal_add_js($base_file, 'module', 'fbml');
     
     // Add some settings that FBJS code will often need.
-    $baseUrl = url('', NULL, NULL, TRUE);
+    $baseUrl = url('', array('absolute' => TRUE));
     drupal_add_js(array('fbjs' => array('baseUrlFb' => $baseUrl,
                                         'baseUrl' => fb_scrub_urls($baseUrl),
                         ),
@@ -788,4 +798,4 @@ function fb_verbose() {
   return variable_get('fb_verbose', NULL);
 }
 
-?>
\ No newline at end of file
+?>
Index: fb_app.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_app.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb_app.info
--- fb_app.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb_app.info	22 Feb 2009 20:13:03 -0000
@@ -1,5 +1,6 @@
 name = DFF Applications
 description = Allows Drupal to host Facebook Applications
 package = Drupal for Facebook
-dependencies = fb
+dependencies[] = fb
+core = 6.x
 
Index: fb_app.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_app.install,v
retrieving revision 1.6
diff -u -p -r1.6 fb_app.install
--- fb_app.install	5 Aug 2008 20:27:30 -0000	1.6
+++ fb_app.install	22 Feb 2009 20:13:03 -0000
@@ -6,36 +6,62 @@
    */
   // TODO: some of these tables should be created by othe module install files.
 
+/**
+ * hook_install()
+ */
 function fb_app_install() {
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      db_query("
-CREATE TABLE IF NOT EXISTS {fb_app} (
-nid int(11) unsigned NOT NULL,
-label varchar(128) NOT NULL,
-apikey varchar(128) NOT NULL,
-id varchar(128) NOT NULL,
-secret varchar(128) NOT NULL,
-canvas varchar(128) NOT NULL,
-require_login int(4) NOT NULL,
-create_account int(4) NOT NULL,
-unique_account int(4) NOT NULL,
-data longtext,
-PRIMARY KEY (nid),
-UNIQUE KEY (apikey)
-) /*!40100 DEFAULT CHARACTER SET UTF8 */;
-");
-
-  }
-  
-  drupal_set_message(t('Facebook Application module installed. Please grant yourself <a href="!perm">permissions</a> and then browse to <a href="!create">Create Content => Facebook Application</a> to get started.', array('!perm' => url('admin/user/access'), '!create' => url('node/add/fb-app'))));
+  // Create tables.
+  drupal_install_schema('fb_app');
   
+  drupal_set_message(t('Facebook Application module installed. Please grant yourself <a href="!perm">permissions</a> and then browse to <a href="!create">Create Content => Facebook Application</a> to get started.', array('!perm' => url('admin/user/permissions'), '!create' => url('node/add/fb-app'))));
 }
 
-function fb_app_update_1() {
-  // Add id field
-  $ret[] = update_sql('ALTER TABLE {fb_app} ADD id varchar(128) NOT NULL');
-  return $ret;
+/**
+ * hook_uninstall()
+ */
+function fb_app_uninstall() {
+  // Remove tables.
+  drupal_uninstall_schema('fb_app');
+}
+
+function fb_app_schema() {
+  $schema['fb_app'] = array(
+    'description' => 'Main FB_APP table',
+    'fields' => array(
+      'nid' => array('type' => 'int', 'length' => 11, 'unsigned' => TRUE, 'not null' => TRUE, ),
+      'label' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+      'apikey' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+      'id' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+      'secret' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+      'canvas' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+      'require_login' => array('type' => 'int', 'length' => 4, 'not null' => TRUE, ),
+      'create_account' => array('type' => 'int', 'length' => 4, 'not null' => TRUE, ),
+      'unique_account' => array('type' => 'int', 'length' => 4, 'not null' => TRUE, ),
+      'rid' => array('type' => 'int', 'length' => 10, 'unsigned' => TRUE, 'not null' => TRUE, ),
+      'data' => array('type' => 'text', 'size' => 'big', ),
+    ),
+    'unique keys' => array(
+      'apikey' => array('apikey'),
+    ),
+    'primary key' => array('nid'),
+  );
+  $schema['fb_app_block'] = array(
+    'fields' => array(
+      'nid' => array('type' => 'int', 'length' => 11, 'unsigned' => TRUE, 'not null' => TRUE, ),
+      'delta' => array('type' => 'varchar', 'length' => 32, 'not null' => TRUE, ),
+      'format' => array('type' => 'int', 'length' => 11, 'default' => 0, ),
+      'body' => array('type' => 'text', 'size' => 'big', 'not null' => TRUE, ),
+    ),
+    'primary key' => array('nid', 'delta'),
+  );
+  $schema['fb_cache_filter'] = drupal_get_schema_unprocessed('system', 'cache');
+
+  return $schema;  
 }
-?>
\ No newline at end of file
+
+function fb_app_update_6100() {
+  // Add id field
+  $ret = array();
+  db_add_field($ret, 'fb_app', 'id', array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ));
+	return $ret;
+}
\ No newline at end of file
Index: fb_app.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_app.module,v
retrieving revision 1.22
diff -u -p -r1.22 fb_app.module
--- fb_app.module	8 Feb 2009 20:41:35 -0000	1.22
+++ fb_app.module	22 Feb 2009 20:13:03 -0000
@@ -79,18 +79,26 @@ function fb_app_fb($op, $data, &$return)
 }
 
 /**
- * hook_menu
+ * Loader callback for drupal menu api.
  */
-function fb_app_menu($may_cache) {
+function fb_app_nid_load($nid) {
+  $node = node_load($nid);
+  if ($node->type == 'fb_app') {
+    return $node;
+  }
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function fb_app_menu() {
   $items = array();
-  if ($may_cache) {
-    // Allow facebook to notify on various events, like adding or removing an app.
-    $items[] = array('path' => FB_APP_PATH_EVENT,
-                     'access' => TRUE,
-                     'callback' => 'fb_app_event_cb',
-                     'type' => MENU_CALLBACK,                     
+  // Allow facebook to notify on various events, like adding or removing an app.
+  $items[FB_APP_PATH_EVENT] = 
+    array('access callback' => TRUE,
+          'page callback' => 'fb_app_event_cb',
+          'type' => MENU_CALLBACK,                     
     );
-  }
   return $items;
 }
 
@@ -122,15 +130,14 @@ function fb_app_node_info() {
   );
 }
 
-function fb_app_access($op, $node) {
-  global $user;
-  if (user_access('administer fb apps'))
+function fb_app_access($op, $node, $account) {
+  if (user_access('administer fb apps', $account))
     return TRUE;
-  if ($op == 'create' && user_access('create fb apps'))
+  if ($op == 'create' && user_access('create fb apps', $account))
     return TRUE;
   else if ($op == 'update' || $op == 'delete') {
     if ($node->uid == $user->uid && 
-        user_access('edit own fb apps'))
+        user_access('edit own fb apps', $account))
       return TRUE;
   }
 }
@@ -266,9 +273,24 @@ function fb_app_view($node, $teaser=FALS
   return $node;
 }
 
+function fb_app_theme() {
+  return array(
+    'fb_app' => array(
+      'arguments' => array('data' => NULL),
+      ),
+    'dl' => array(
+      'arguments' => array('items' => NULL),
+      ),
+    'fb_app_user_info' => array(
+      'arguments' => array('fb_app' => NULL, 'info' => NULL),
+      ),
+  );
+}
+
 function fb_app_get_about_url($fb_app) {
   if ($fb_app->id)
-    return url("http://www.facebook.com/apps/application.php", "id=$fb_app->id");
+    return url("http://www.facebook.com/apps/application.php", 
+               array('query' => array('id' => $fb_app->id)));
 }
 
 function theme_fb_app($fb_app) {
@@ -283,7 +305,7 @@ function theme_fb_app($fb_app) {
     if ($fb_app->$key)
       $data[$name] = $fb_app->$key;
   }
-  $about_url = fb_app_get_about_url($data);
+
   $output .= theme('dl', $data);
   return $output;
 }
@@ -472,7 +494,7 @@ function fb_app_user($op, &$edit, &$acco
 function theme_fb_app_user_info($fb_app, $info) {
   if ($info['pic_big'])
     $output .= '<p><img src="'.$info['pic_big'].'" /></p>';
-  $fb_link = l($info['name'], 'http://www.facebook.com/profile.php', NULL, 'id='.$info['uid']);
+  $fb_link = l($info['name'], 'http://www.facebook.com/profile.php', array('query' => 'id=' . $info['uid']));
   if ($info['is_app_user'])
     $output .= '<p>' . t('!fb_link uses %title',
                          array('!fb_link' => $fb_link,
@@ -503,5 +525,4 @@ function fb_app_token_values($type = 'al
   }
   return $values;
 }
-
 ?>
\ No newline at end of file
Index: fb_canvas.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_canvas.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb_canvas.info
--- fb_canvas.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb_canvas.info	22 Feb 2009 20:13:03 -0000
@@ -1,5 +1,6 @@
 name = DFF Canvas Pages
 description = Support for Facebook Canvas Pages.  You will also need an FBML theme.
 package = Drupal for Facebook
-dependencies = fb fb_app
-
+dependencies[] = fb
+dependencies[] = fb_app
+core = 6.x
Index: fb_canvas.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_canvas.module,v
retrieving revision 1.22
diff -u -p -r1.22 fb_canvas.module
--- fb_canvas.module	5 Feb 2009 02:47:28 -0000	1.22
+++ fb_canvas.module	22 Feb 2009 20:13:03 -0000
@@ -7,13 +7,14 @@
  * 
  */
 
-function fb_canvas_menu($may_cache) {
+function fb_canvas_menu() {
   $items = array();
   if ($may_cache) {
-    $items[] = array('path' => 'fb/canvas/session',
-		     'callback' => 'fb_canvas_session_cb',
-		     'type' => MENU_CALLBACK,
-		     'access' => TRUE);
+    $items['fb/canvas/session'] = array(
+      'page callback' => 'fb_canvas_session_cb',
+      'type' => MENU_CALLBACK,
+      'access callback' => TRUE,
+    );
   }
   return $items;
 }
@@ -51,7 +52,7 @@ function fb_canvas_block($op = 'list', $
     }
     $_SESSION['fb_canvas_session'] = TRUE;
 
-    $url = url('fb/canvas/session', NULL, NULL, TRUE);
+    $url = url('fb/canvas/session', array('absolute' => TRUE));
     return array('subject' => NULL,
 		 'content' => "<fb:iframe width=0 height=0 frameborder=0 src=$url></fb:iframe>");
   }
@@ -76,17 +77,15 @@ function fb_canvas_fb($op, $data, &$retu
     else if (fb_canvas_is_iframe())
       $custom_theme = $fb_canvas_data['theme_iframe'];
     
-    // This is for backward compatability (delete eventually)
-    if (!$custom_theme)
-      $custom_theme = variable_get('fb_theme', 'fb_fbml');
+    if (fb_verbose() && FALSE) // Useful for debugging FBML errors
+      watchdog('fb_debug', "setting custom_theme to $custom_theme in fb_canvas_fb");
     
-
     // Special handling for forms, as they are submitted directly to us, not
     // to apps.facebook.com/canvas
     // we will buffer, and later cache, the results.
     if (fb_canvas_handling_form())
       ob_start();
-
+    
     //drupal_set_message("fb_canvas_fb" . dpr($_GET, 1) . 'arg(0) = ' . dpr(arg(0), 1) . 'arg(1) = ' . dpr(arg(1), 1) . 'frontpage ' . dpr(variable_get('site_frontpage', 'node'), 1));
     if ($_GET['q'] == drupal_get_normal_path(variable_get('site_frontpage', 'node'))) {
       if ($fb->get_loggedin_user()) {
@@ -109,6 +108,7 @@ function fb_canvas_fb($op, $data, &$retu
       ob_end_clean();
       
       if ($destination) {
+        watchdog('fb_debug', "FB_OP_EXIT, handling form, original destination: $destination");
         // Fully qualified URLs need to be modified to point to facebook app.
         // URLs are fully qualified when a form submit handler returns a path,
         // or any call to drupal_goto.
@@ -118,6 +118,7 @@ function fb_canvas_fb($op, $data, &$retu
         // canvas page, so we'll use Facebook's method.
         // Will this preempt other hook_exits?
         if ($fb) {
+          watchdog('fb_debug', "FB_OP_EXIT, handling form, redirecting to $destination");
           $fb->redirect($destination);
         }
       }
@@ -126,7 +127,7 @@ function fb_canvas_fb($op, $data, &$retu
         $token = uniqid('fb_');
         $cid = session_id() . "_$token";
         watchdog('fb', "Storing cached form page $cid, then redirecting");
-        cache_set($cid, 'cache_page', $output, time() + (60 * 5), drupal_get_headers()); // (60 * 5) == 5 minutes
+        cache_set($cid, $output, 'cache_page', time() + (60 * 5), drupal_get_headers()); // (60 * 5) == 5 minutes
         
         $dest = 'http://apps.facebook.com/' . $fb_app->canvas . "/fb/form_cache/$cid";
         // $fb->redirect($url); // Does not work!
@@ -164,7 +165,7 @@ function fb_canvas_fb($op, $data, &$retu
 /**
  * Implementation of hook_form_alter.
  */
-function fb_canvas_form_alter($form_id, &$form) {
+function fb_canvas_form_alter(&$form, &$form_state, $form_id) {
   // Add our settings to the fb_app edit form.
   if (is_array($form['fb_app_data'])) {
     $node = $form['#node'];
@@ -205,31 +206,34 @@ function fb_canvas_form_alter($form_id, 
             '#default_value' => $fb_canvas_data['front_added'],
       );
     
+    /* XXX menu code here needs updating to D6
     // Allow primary links to be different on facebook versus the rest of the
     // site.  Code from menu_configure() in menu.module.
-    $root_menus = menu_get_root_menus();
-    
-    $primary_options = $root_menus;
-    $primary_options[0] = t('<use sitewide setting>');
-    $secondary_options = $root_menus;
-    $secondary_options[0] = t('<use sitewide setting>');
-    
-    $form['fb_app_data']['fb_canvas']['primary_links'] =
-      array('#type' => 'select',
-            '#title' => t('Menu containing primary links'),
-            '#description' => t('Your application can have primary links different from those used elsewhere on your site.'),
-            '#default_value' => $fb_canvas_data['primary_links'],
-            '#options' => $primary_options,
-	    );
-    $form['fb_app_data']['fb_canvas']['secondary_links'] = 
-      array('#type' => 'select',
-            '#title' => t('Menu containing secondary links'),
-            '#default_value' => $fb_canvas_data['secondary_links'],
-            '#options' => $secondary_options,
-            '#description' => t('If you select the same menu as primary links then secondary links will display the appropriate second level of your navigation hierarchy.'),
+
+    $primary = variable_get('menu_primary_links_source', 'primary-links');
+    $primary_options = array_merge($menu_options, array('' => t('<use sitewide setting>')));
+    $form['fb_app_data']['fb_canvas']['menu_primary_links_source'] = 
+      array(
+        '#type' => 'select',
+        '#title' => t('Source for the primary links'),
+        '#default_value' => $fb_canvas_data['primary_links'],
+        '#options' => $primary_options,
+        '#tree' => FALSE,
+        '#description' => t('Your application can have primary links different from those used elsewhere on your site.'),
       );
-    
-    
+
+    $secondary_options = array_merge($menu_options, array('' => t('<use sitewide setting>')));
+    $form['fb_app_data']['fb_canvas']['menu_secondary_links_source'] = 
+      array(
+        '#type' => 'select',
+        '#title' => t('Source for the secondary links'),
+        '#default_value' => $fb_canvas_data['secondary_links'],
+        '#options' => $secondary_options,
+        '#tree' => FALSE,
+        '#description' => t('If you select the same menu as primary links then secondary links will display the appropriate second level of your navigation hierarchy.'),
+      );
+*/
+
     // Override themes
     $themes = system_theme_data();
     ksort($themes);
@@ -282,6 +286,15 @@ function fb_canvas_form_alter($form_id, 
       // We've stored #action_old and #action_new so custom modules have the option to change it back.
     }
 
+    // Drupal includes wacky markup for javascript junk in node forms.  It
+    // makes things look terrible in FBML.  It only works when javascript is
+    // enabled and it should have been implemented to degrade gracefully, but
+    // it wasn't.
+    if ($form['body_field']) {
+      unset($form['body_field']['teaser_js']);
+      unset($form['body_field']['teaser_include']);            
+    }
+
   }
   else if (fb_canvas_is_iframe()) {
     //dpm($form, 'fb_canvas_form_alter');
@@ -306,7 +319,7 @@ function fb_canvas_nodeapi(&$node, $op, 
       $output = theme('dl', 
                       array(t('Canvas URL') => "http://apps.facebook.com/$fb_app->canvas",
                       ));
-
+      
       $node->content['fb_canvas'] = 
         array('#value' => $output,
               '#weight' => 2);
@@ -343,10 +356,13 @@ function fb_canvas_handling_form() {
 
 // This may need work
 function _fb_canvas_make_form_action_local($action) {
+  //dpm($action, "_fb_canvas_make_form_action_local");
+  global $base_path;
+
   // If action is fully qualified, do not change it
   if (strpos($action, ':'))
     return $action;
-
+  
   // I'm not sure where the problem is, but sometimes actions have two question marks.  I.e.
   // /htdocs/?app=foo&q=user/login?destination=comment/reply/1%2523comment-form
   // Here we replace 3rd (or more) '?' with '&'.
@@ -356,8 +372,25 @@ function _fb_canvas_make_form_action_loc
     $action .= '&' . implode('&', $parts);
   }
   
+  $relative = url('');
+  $absolute = url('', array('absolute'=>TRUE));
+  global $fb_app;
+
+  if (strpos($action, FB_SETTINGS_APP_NID)) {
+    $action = $absolute . substr($action, strlen($relative));
+  }
+  else if (strpos($action, $relative) === 0) {
+    // Replace relative action with absolute.
+    // Include fb settings
+    // TODO: FB_SETTINGS_PAGE_TYPE
+    $action = $absolute . FB_SETTINGS_APP_NID . '/' . $fb_app->nid . '/' . substr($action, strlen($relative));
+  }
+  
+  //dpm($action, '_fb_canvas_make_form_action_local returning');
+  return $action;
+
   //drupal_set_message("form action now " . "http://".$_SERVER['HTTP_HOST']. $action); // debug
-  return "http://".$_SERVER['HTTP_HOST']. $action;
+  //return "http://".$_SERVER['HTTP_HOST']. $action;
 }
 
 /**
@@ -366,7 +399,7 @@ function _fb_canvas_make_form_action_loc
 function fb_canvas_goto($path) {
   global $fb, $fb_app;
   if ($fb && (fb_canvas_is_fbml() || fb_canvas_is_iframe())) {
-    $url = fb_canvas_fix_url(url($path, NULL, NULL, TRUE), $fb_app);
+    $url = fb_canvas_fix_url(url($path, array('absolute' => TRUE)), $fb_app);
     $fb->redirect($url);
   }
   else {
@@ -384,9 +417,16 @@ function fb_canvas_goto($path) {
 function fb_canvas_fix_url($url, $fb_app) {
 
   global $base_url;
+
+
   $patterns[] = "|{$base_url}/" . FB_SETTINGS_APP_NID . "/{$fb_app->nid}/|";
   // Here we assume apps.facebook.com.  Is this safe?
   $replacements[] = "http://apps.facebook.com/{$fb_app->canvas}/";
+
+  // fully qualified paths
+  $patterns[] = "|".url('', array('absolute' => TRUE))."|";
+  $replacements[] = "http://apps.facebook.com/{$fb_app->canvas}/";
+  
   
   $patterns[] = "|fb_cb_type/[^/]*/|";
   $replacements[] = "";
@@ -394,8 +434,12 @@ function fb_canvas_fix_url($url, $fb_app
   // Facebook will prepend "appNNN_" all our ids
   $patterns[] = "|#([^\?]*)|";
   $replacements[] = "#app{$fb_app->id}_$1";
+
+  watchdog('fb_debug', "fb_canvas_fix_url($url), patterns: " . dprint_r($patterns, 1) . " replacements: " . dprint_r($replacements, 1));
   
   $url = preg_replace($patterns, $replacements, $url);
+  watchdog('fb_debug', "fb_canvas_fix_url returning $url");
+
   return $url;
 }
 
@@ -464,11 +508,19 @@ function fb_canvas_process($output, $add
   if ($fb) {
     $page_type = fb_settings(FB_SETTINGS_PAGE_TYPE);
     $nid = $fb_app->nid;
-    $base = url();  // short URL with rewrite applied.
+    $base_before_rewrite = '';
+    $base = $base_path . fb_settings_url_rewrite_outbound($base_before_rewrite, NULL, NULL);  // short URL with rewrite applied.
     if (fb_canvas_is_fbml()) {
       //dpm($output, "before fb_canvas_process");
       // We're producing FBML for a canvas page
       
+      /*
+      TODO: $output['logo'] is not being processed properly by these
+      patterns. fb_canvas_process() returns '/sites/all/themes/fb_fbml/logo.png'
+      and Facebook complains "Relative URLs not allowed here"
+      
+      */
+      
       // Change links to use canvas on Facebook
       // Links ending in #something:
       $patterns[] = "|=\"{$base}([^\"]*#)|";
@@ -535,6 +587,9 @@ function fb_canvas_process($output, $add
     }
   }
   if (count($patterns)) {
+    //dpm($patterns, "fb_canvas_process patterns");
+    //dpm($replacements, "fb_canvas_process replacements");
+
     $return = preg_replace($patterns,
 			   $replacements,
 			   $output);
@@ -574,4 +629,5 @@ function fb_canvas_process_fbml($output,
   else
 	return $output;
 }
+
 ?>
\ No newline at end of file
Index: fb_connect.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_connect.module,v
retrieving revision 1.7
diff -u -p -r1.7 fb_connect.module
--- fb_connect.module	10 Feb 2009 23:39:59 -0000	1.7
+++ fb_connect.module	22 Feb 2009 20:13:03 -0000
@@ -116,7 +116,7 @@ function fb_connect_user($op, &$edit, &$
 	  $session_key = $fb->api_client->session_key;
 	  // http://forum.developers.facebook.com/viewtopic.php?id=21879
 	  // Use next parameter to expire session.
-	  drupal_goto("http://www.facebook.com/logout.php?app_key={$fb_app->apikey}&session_key={$session_key}&next=" . url('<front>', NULL, NULL, TRUE));
+	  drupal_goto("http://www.facebook.com/logout.php?app_key={$fb_app->apikey}&session_key={$session_key}&next=" . url('<front>', array('absolute' => TRUE)));
 	}
       } catch (Exception $e) {
 	fb_log_exception($e, t('Failed to log out of fbConnect session'));
Index: fb_devel.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_devel.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb_devel.info
--- fb_devel.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb_devel.info	22 Feb 2009 20:13:03 -0000
@@ -1,6 +1,9 @@
 name = DFF Devel
 description = Blocks and messages that help when developing and debugging Apps.
 package = Drupal for Facebook
-dependencies = fb devel
+dependencies[] = fb
+dependencies[] = devel
+core = 6.x
+
 
 
Index: fb_devel.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_devel.module,v
retrieving revision 1.11
diff -u -p -r1.11 fb_devel.module
--- fb_devel.module	3 Feb 2009 22:54:42 -0000	1.11
+++ fb_devel.module	22 Feb 2009 20:13:03 -0000
@@ -1,20 +1,16 @@
 <?php
 
-function fb_devel_menu($may_cache) {
-  $items = array();
-
-  if ($may_cache) {
-    $items[] = array('path' => 'fb/devel',
-                     'callback' => 'fb_devel_page',
-                     'type' => MENU_CALLBACK,
-                     'access' => TRUE, // TODO: restrict access
-    );
-    $items[] = array('path' => 'fb/devel/fbu',
-                     'callback' => 'fb_devel_fbu_page',
-                     'type' => MENU_CALLBACK,
-                     'access' => TRUE,
-    );
-  }
+function fb_devel_menu() {
+  $items['fb/debug'] = array('page callback' => 'fb_devel_cb',
+                             'type' => MENU_CALLBACK,
+                             'access callback' => TRUE, /* TODO: restrict access */
+  );
+  
+  $items['fb/devel/fbu'] = array('page callback' => 'fb_devel_fbu_page',
+                                 'type' => MENU_CALLBACK,
+                                 'access' => TRUE,
+  );
+  
   return $items;
 }
 
@@ -33,7 +29,7 @@ function fb_devel_fb($op, $data, &$retur
                          '!url' => "http://www.facebook.com/developers/apps.php",
                    ));
       drupal_set_message($message, 'error');
-      watchdog('fb_devel', $message);
+      watchdog('fb_devel', $message, array(), WATCHDOG_ERROR);
     }
     
     // Theme sanity check
@@ -45,7 +41,7 @@ function fb_devel_fb($op, $data, &$retur
                          // disabled.
                          '!readme' => '<a href='.base_path() . '/' . drupal_get_path('module', 'fb') . '/README.txt>README.txt</a>'));
       drupal_set_message($message, 'error');
-      watchdog('fb_devel', $message);      
+      watchdog('fb_devel', $message, array(), WATCHDOG_ERROR);
     }
 
     // path replacement sanity check
@@ -68,7 +64,10 @@ function fb_devel_fb($op, $data, &$retur
     $message .= dprint_r($_REQUEST,1);
     watchdog('fb_devel', $message);
   }
-
+  
+  else if ($op == FB_OP_CANVAS_EXIT && $data['fb'] && $return) {
+    watchdog('fb_devel', t('Drupal is redirecting a canvas page, destination is %destination.', array('%destination' => $return)));
+  }
 }
 
 /**
@@ -181,6 +180,8 @@ function fb_devel_canvas_info() {
       $info['Page Status'] = t('Global fb instance is set (followed link in iframe, or handling a form).');
     }
     $info['fb_facebook_user'] = fb_facebook_user();
+    // users_isAppUser() may be unreliable!
+    $info['users_isAppUser'] = $fb->api_client->users_isAppUser();
   }
   else {
     $info['Page Status'] = t('Not a canvas page.');
@@ -197,6 +198,11 @@ function fb_devel_canvas_info() {
   $info['fb_app'] = $fb_app;
   $info['session'] = $_SESSION;
   $info['cookies'] = $_COOKIE;
+
+  if ($fb) {
+    $info['api_client'] = $fb->api_client;
+  }
+
   $form = array();
   foreach ($info as $key => $val) {
     if (is_string($val) || is_numeric($val) || !$val) {
Index: fb_feed.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_feed.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb_feed.info
--- fb_feed.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb_feed.info	22 Feb 2009 20:13:03 -0000
@@ -1,4 +1,5 @@
 name = DFF Feeds
 description = Manage Facebook feed templates and post to feeds.
 package = Drupal for Facebook
-dependencies = fb
+dependencies[] = fb
+core = 6.x
Index: fb_feed.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_feed.module,v
retrieving revision 1.9
diff -u -p -r1.9 fb_feed.module
--- fb_feed.module	2 Feb 2009 19:35:37 -0000	1.9
+++ fb_feed.module	22 Feb 2009 20:13:04 -0000
@@ -16,39 +16,31 @@ define('FB_FEED_NODE_TYPE_TEMPLATE', 'fb
 define('FB_FEED_HOOK', 'fb_feed');
 define('FB_FEED_OP_TOKEN_ALTER', 'fb_feed_token_alter');
 
-function fb_feed_menu($may_cache) {
+function fb_feed_menu() {
   $items = array();
-  if ($may_cache) {
-    $items[] = array('path' => 'fb_feed/register',
-                     'title' => t('Register template'),
-                     'type' => MENU_CALLBACK,
-                     'access' => user_access('administer fb apps'),
-                     'callback' => 'fb_feed_register_cb',
-    );
-    $items[] = array('path' => 'fb_feed/deactivate',
-                     'title' => t('Deactivate template'),
-                     'type' => MENU_CALLBACK,
-                     'access' => user_access('administer fb apps'),
-                     'callback' => 'drupal_get_form',
-                     'callback arguments' => array('fb_feed_deactivate_confirm'),
-    );
-
-  }
-  else {
-    if (arg(0) == 'node' && is_numeric(arg(1))) {
-      $node = node_load(arg(1));
-      if ($node->type == 'fb_app') {
-        $fb_app_data = fb_app_get_data($node->fb_app);
-        $items[] = array('path' => "node/$node->nid/fb_feed/templates",
-                         'title' => t('Feed Templates'),
-                         'type' => MENU_LOCAL_TASK,
-                         'access' => node_access('update', $node),
-                         'callback' => 'fb_feed_template_page',
-                         'callback arguments' => array($node->nid),
-        );
-      }
-    }
-  }
+  $items['fb_feed/register'] = array(
+    'title' => 'Register template',
+    'type' => MENU_CALLBACK,
+    'access arguments' => array('adminster fb apps'),
+    'page callback' => 'fb_feed_register_cb',
+  );
+  $items['fb_feed/deactivate'] = array(
+    'title' => 'Deactivate template',
+    'type' => MENU_CALLBACK,
+    'access arguments' => array('adminster fb apps'),
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('fb_feed_deactivate_confirm'),
+  );
+  
+  $items['node/%fb_app_nid/fb_feed/templates'] = array(
+    'title' => t('Feed Templates'),
+    'type' => MENU_LOCAL_TASK,
+    'access callback' => 'node_access',
+    'access arguments' => array('update', 1),
+    'page callback' => 'fb_feed_template_page',
+    'page arguments' => array(1),
+  );
+  
   return $items;
 }
 
@@ -112,7 +104,7 @@ function fb_feed_register_cb($nid) {
   drupal_goto('node/'.$node->fb_app_nid.'/fb_feed/templates');
 }
 
-function fb_feed_template_page($fb_app_nid) {
+function fb_feed_template_page($fb_app) {
   $registered = array();
   $unregistered = array();
   // Query all known templates
@@ -127,7 +119,6 @@ function fb_feed_template_page($fb_app_n
   }
   
   // Query facebook for a list of registered templates we know nothing about.
-  $fb_app = fb_get_app(array('nid' => $fb_app_nid));
   $fb = fb_api_init($fb_app, FB_FBU_ANY);
   if ($fb) {
     try {
Index: fb_form.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_form.info,v
retrieving revision 1.3
diff -u -p -r1.3 fb_form.info
--- fb_form.info	5 Feb 2009 03:34:50 -0000	1.3
+++ fb_form.info	22 Feb 2009 20:13:04 -0000
@@ -1,4 +1,5 @@
 name = DFF Forms
 description = Enables FBML form elements via Drupal Form API.  Provides commonly needed forms such as invite friends to install application.
 package = Drupal for Facebook
-dependencies = fb
+dependencies[] = fb
+core = 6.x
Index: fb_form.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_form.module,v
retrieving revision 1.13
diff -u -p -r1.13 fb_form.module
--- fb_form.module	26 Sep 2008 20:06:30 -0000	1.13
+++ fb_form.module	22 Feb 2009 20:13:04 -0000
@@ -15,30 +15,27 @@
 /**
  * hook_menu.
  */
-function fb_form_menu($may_cache) {
+function fb_form_menu() {
   $items = array();
-  if ($may_cache) {
-    // Page allowing a user to invite their friends to add the app.
-    $items[] = array('path' => 'fb/invite',
-                     'callback' => 'fb_form_invite_page',
-                     'access' => TRUE,
-                     'type' => MENU_CALLBACK,
-    );
-    $items[] = array('path' => 'fb_form_friend_selector_autocomplete',
-                     'callback' => 'fb_form_friend_selector_autocomplete',
-                     'access' => TRUE,
-                     'type' => MENU_CALLBACK,
-    );
-  }
+  // Page allowing a user to invite their friends to add the app.
+  $items['fb/invite'] = 
+    array('page callback' => 'fb_form_invite_page',
+	  'access callback' => TRUE,
+	  'type' => MENU_CALLBACK,
+	  );
+  $items['fb_form_friend_selector_autocomplete'] = 
+    array('page callback' => 'fb_form_friend_selector_autocomplete',
+	  'access callback' => TRUE,
+	  'type' => MENU_CALLBACK,
+	  );
   return $items;
 }
 
 /**
  * hook_form_alter.
  */
-function fb_form_form_alter($form_id, &$form) {
-  // Drupal allows no clean way to set $form['#type'], so we hack.
-
+function fb_form_form_alter(&$form, &$form_state, $form_id) {
+  /* Drupal allows no clean way to set $form['#type'], so we hack... */
   if ($type = $form['#fb_form_type_hack']) {
     $form['#type'] = $type;
     unset($form['#fb_form_type_hack']);
@@ -121,7 +118,7 @@ function fb_form_invite_page() {
 
   if (function_exists('fb_canvas_is_fbml') &&
       !fb_canvas_is_fbml()) {
-    drupal_set_message(t('Unable to display page.  FBML required.'), 'error');
+    drupal_set_message('Unable to display page.  FBML required.', 'error');
     drupal_not_found();
     exit();
   }
@@ -259,7 +256,7 @@ function fb_form_friend_options($fbu) {
   $items = array();
 
   if ($fb) {
-    $query = "SELECT last_name, first_name, uid, pic_square FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$fbu)";
+    $query = "SELECT last_name, first_name, uid, pic_square FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=$fbu)"; //TODO: db_query this to be safe?
     $result = $fb->api_client->fql_query($query);
     
     // TODO: sort results by name
@@ -273,14 +270,14 @@ function fb_form_friend_options($fbu) {
 function fb_form_group_member_options($fbg, $fbu) {
   global $fb;
 
-  $query = "SELECT uid FROM group_member WHERE gid=$fbg";
+  $query = "SELECT uid FROM group_member WHERE gid=$fbg"; //TODO: db_query this?
   $result = $fb->api_client->fql_query($query);
   drupal_set_message("fb_form_group_member_options($fbg, $fbu) query $query returns" . dpr($result, 1));
 
 
 
 
-  $query = "SELECT uid, first_name, last_name FROM user WHERE uid IN (SELECT uid FROM group_member WHERE gid=$fbg)";
+  $query = "SELECT uid, first_name, last_name FROM user WHERE uid IN (SELECT uid FROM group_member WHERE gid=$fbg)"; //TODO: db_query to be safe?
   $result = $fb->api_client->fql_query($query);
   drupal_set_message("fb_form_group_member_options($fbg, $fbu) query $query returns" . dpr($result, 1));
 
@@ -384,7 +381,7 @@ function fb_form_friend_selector_process
   else
     $element['#type'] = 'textfield';
 
-  $element['#autocomplete_path'] = url('fb_form_friend_selector_autocomplete', NULL, NULL, TRUE);
+  $element['#autocomplete_path'] = url('fb_form_friend_selector_autocomplete', array('absolute' => TRUE));
   return $element;
 }
 
@@ -472,6 +469,14 @@ function fb_form_friend_selector_validat
   _form_set_value($_POST, $element, $element['#parents'], $items);
 }
 
+function fb_form_theme() {
+  return array(
+    'friend_selectorXXX' => array(
+      'arguments' => array('fbu' => NULL),
+      ),
+    );
+}
+
 // TODO: provide some alternative when NOT a facebook app.
 // deprecated!
 function theme_fb_form_friend_selector($fbu = NULL) {
@@ -482,4 +487,3 @@ function theme_fb_form_friend_selector($
   $output = "<fb:friend-selector uid=\"$fbu\" name=\"fbname\" idname=\"fbu\" />";
   return $output;
 }
-?>
\ No newline at end of file
Index: fb_infinite.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_infinite.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb_infinite.info
--- fb_infinite.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb_infinite.info	22 Feb 2009 20:13:04 -0000
@@ -1,5 +1,5 @@
 name = DFF Infinite Session
 description = Some app administration requires a session.  Use this module, or Facebook Connect, with the Feeds module.
 package = Drupal for Facebook
-dependencies = fb fb_app
-
+dependencies[] = fb
+core = 6.x
Index: fb_infinite.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_infinite.module,v
retrieving revision 1.7
diff -u -p -r1.7 fb_infinite.module
--- fb_infinite.module	2 Feb 2009 19:36:27 -0000	1.7
+++ fb_infinite.module	22 Feb 2009 20:13:04 -0000
@@ -27,43 +27,51 @@ function fb_infinite_fb($op, $data, &$re
 /**
  * hook_menu
  */
-function fb_infinite_menu($may_cache) {
-  $items = array();
-  if ($may_cache) {
-    $items[] = array('path' => 'fb/infinite/display',
-                     'title' => t('Facebook session information'),
-                     'access' => TRUE,
-                     'callback' => 'fb_infinite_display_page',
-                     'type' => MENU_CALLBACK,
+function fb_infinite_menu() {
+  $items['fb/infinite/display'] = 
+    array('title' => t('Facebook session information'),
+          'page callback' => 'fb_infinite_display_page',
+          'access callback' => TRUE,
+          'type' => MENU_CALLBACK,
     );
-  }
-  else {
-    if (arg(0) == 'node' && is_numeric(arg(1))) {
-      $node = node_load(arg(1));
-      if ($node->type == 'fb_app') {
-        // Only show if infinite session is configured.
-        $fb_app_data = fb_app_get_data($node->fb_app);
-        $fb_infinite_data = $fb_app_data['fb_infinite'];
-        if ($fb_infinite_data['key']) {
-          $items[] = array('path' => "node/$node->nid/fb/infinite/test",
-                           'title' => t('Infinite session test'),
-                           'type' => MENU_LOCAL_TASK,
-                           'access' => node_access('update', $node),
-                           'callback' => 'fb_infinite_test_page',
-                           'callback arguments' => array($node->nid),
-          );
-        }
-      }
+
+  $items['node/%fb_infinite/fb/infinite/test'] = 
+    array('title' => 'Infinite session test',
+          'page callback' => 'fb_infinite_test_page',
+          'page arguments' => array(1),
+          'access callback' => 'node_access',
+          'access arguments' => array('update', 1),
+          'type' => MENU_LOCAL_TASK,
+    );
+  
+  return $items;
+}
+
+
+/**
+ * Implementation of hook_load to create custom loader for hook_menu
+ * Checks a fb_app nid to see if infinite session is configured
+ *
+ * see "Defining your own wildcard loader" - http://drupal.org/node/209056
+ * passing $nid not needed if menu_get_object were to work
+ */
+function fb_infinite_load($nid) {
+  $fb_app = fb_get_app(array('nid' => $nid));
+  if ($fb_app) {
+    // Only allow menu item if infinite session is configured.
+    $fb_app_data = fb_app_get_data($fb_app);
+    $fb_infinite_data = $fb_app_data['fb_infinite'];
+    if (isset($fb_infinite_data['key'])) {
+      return $fb_app;
     }
   }
-  return $items;
 }
 
 /**
  * Implementation of hook_form_alter.
  */
-function fb_infinite_form_alter($form_id, &$form) {
-  //drupal_set_message("fb_infinte_form_alter($form_id) " . dpr($form, 1));
+function fb_infinite_form_alter(&$form, &$form_state, $form_id) {
+  //drupal_set_message("fb_infinite_form_alter($form_id) " . dpr($form, 1)) . dpr($form_state, 1));
   
   // Add our settings to the fb_app edit form.
   if (is_array($form['fb_app_data'])) {
@@ -120,7 +128,7 @@ function fb_infinite_form_alter($form_id
 
 function fb_infinite_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
   if ($node->type == 'fb_app') {
-    if ($op == 'submit') {
+    if ($op == 'presave') {
       $fb_app_data = $node->fb_app_data;
       $fb_infinite_data = $fb_app_data['fb_infinite'];
 
@@ -169,14 +177,13 @@ function fb_infinite_display_page() {
 /**
  * Menu callback to test infinite session values.
  */
-function fb_infinite_test_page($nid) {
+function fb_infinite_test_page($fb_app) {
   if ($GLOBALS['fb']) {
     $url = $GLOBALS['fb_old_base_url'] . "?q=".$_GET['q'];
     return t('Do not use this page from a canvas page.  Try !link.',
              array('!link' => l($url, $url)));
   }
-
-  $fb_app = fb_get_app(array('nid' => $nid));
+  
   $fb = fb_api_init($fb_app, FB_FBU_INFINITE_SESSION);
   if ($fb) {
     $fbu = $fb->api_client->users_getLoggedInUser();
@@ -206,11 +213,11 @@ function fb_infinite_test_page($nid) {
     }
   }
   else {
-    drupal_set_message(t('Infinite session key test failed.'), 'error');
-    $output .= '<p>'.t('Unable to log initialize Facebook API.').'</p>';
+    drupal_set_message('Infinite session key test failed.', 'error');
+    // TODO: provide helpful hints of how to fix the problem.
+    $output .= '<p>'.t('Unable to log into Facebook using infinite session key.').'</p>';
   }
-    
+  
   return $output;
 }
 
-?>
\ No newline at end of file
Index: fb_settings.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_settings.inc,v
retrieving revision 1.5
diff -u -p -r1.5 fb_settings.inc
--- fb_settings.inc	10 Feb 2009 23:39:59 -0000	1.5
+++ fb_settings.inc	22 Feb 2009 20:13:04 -0000
@@ -5,6 +5,7 @@ define('FB_SETTINGS_APP_NID', 'fb_cb');
 define('FB_SETTINGS_PAGE_TYPE', 'fb_cb_type');
 define('FB_SETTINGS_SESSION_KEY', 'fb_sess');
 
+// NOTE: can't use variable_set() -- database.inc hasn't loaded yet, so db_query() in variable_set() fails
 if (!is_array($conf))
   $conf = array();
 
@@ -47,20 +48,46 @@ if ($nid = _fb_settings_parse(FB_SETTING
 }
 
 /**
- * Implementation of conf_url_rewrite
+ * Implementation of conf_url_rewrite_inbound
  * 
  * Defines the URL rewrite if not defined already.  If it is defined already,
- * or your using 118n modules, you should define a custom_url_rewrite in
- * settings.php which calls fb_canvas_url_rewrite in addition to any others
+ * or your using 118n modules, you should define a custom_url_rewrite_inbound in
+ * settings.php which calls fb_canvas_url_rewrite_inbound in addition to any others
  * that need to be called.  The order will be important!
  */
 
-if(!function_exists('custom_url_rewrite')) {
-  function custom_url_rewrite($type, $path, $original) {
-    return fb_settings_url_rewrite($type, $path, $original);
+//TODO: this needs confirmation.
+//custom_url_rewrite was dropped in 6.x so I split the 'source' portion of the old function
+//into _inbound and the 'alias' portion into _outbound versions
+//really guessing here, but it seems to be working
+if(!function_exists('custom_url_rewrite_inbound')) {
+  function custom_url_rewrite_inbound(&$result, $path, $path_language) {
+    fb_settings_url_rewrite_inbound($result, $path, $path_language);
   }
 }  
 
+if(!function_exists('custom_url_rewrite_outbound')) {
+  function custom_url_rewrite_outbound(&$path, $options, $original_path) {
+    fb_settings_url_rewrite_outbound($path, $options, $original_path);
+  }
+}
+
+//TODO: especially verify this one - not sure what to do with Absolute paths, if anything
+//TODO: problem with _fb_canvas_make_form_action_local - is it caused by this?
+//TODO: I don't think the fb_canvas_is_fbml() and fb_canvas_is_iframe() functions are returning the right values either
+function fb_settings_url_rewrite_outbound(&$path, $options, $original_path) {
+  //dpm(func_get_args(), 'fb_settings_url_rewrite_outbound');
+  $pre = '';
+  
+  // Prefix each known value to the URL
+  foreach (array_reverse(_fb_settings_url_rewrite_prefixes()) as $prefix) {
+    if ($value = fb_settings($prefix))
+      $pre .= $prefix . '/'. $value . '/';
+  }
+  $path  = $pre . $path;
+  
+  return $path;
+}
 
 /**
  * Rewrite URLs for facebook canvas pages.
@@ -69,43 +96,43 @@ if(!function_exists('custom_url_rewrite'
  * set when serving canvas pages.  However, it gets called before
  * modules are loaded.  So it must live here.
  */
-function fb_settings_url_rewrite($type, $path, $original){
-  //dpm(func_get_args(), 'fb_canvas_url_rewrite');
-  //print("fb_canvas_url_rewrite($type, $path, $original)");
-  $prefixes = array(FB_SETTINGS_APP_NID, FB_SETTINGS_PAGE_TYPE, FB_SETTINGS_SESSION_KEY);
-  if ($type == 'source') {
-    // See if this is a request for us.
-    if (strpos($path, FB_SETTINGS_APP_NID . '/') === 0) {
-	  // Too soon for arg() function.
-      $args = explode('/', $path);
-      while (count($args) && in_array($args[0], $prefixes)) {
-        $key = array_shift($args);
-        $value = array_shift($args);
-        fb_settings($key, $value); // Store for use later.
+function fb_settings_url_rewrite_inbound(&$result, $path, $path_language){
+  //$origpath = $path;
+  //watchdog('fb_settings', "fb_settings_url_rewrite_inbound($result, $path, $path_language)", array(), WATCHDOG_DEBUG);
+  
+  // See if this is a request for us.
+  if (strpos($path, FB_SETTINGS_APP_NID . '/') === 0) {
+    // Too soon for arg() function.
+    $args = explode('/', $path);
+    while (count($args) && in_array($args[0], _fb_settings_url_rewrite_prefixes())) {
+      $key = array_shift($args);
+      $value = array_shift($args);
+      $app_nid = fb_settings($key, $value); // Store for use later.
+    }
+    if ($app_nid = fb_settings(FB_SETTINGS_APP_NID)) {
+      if (count($args)) {
+        $path = implode('/', $args); // remaining args
+        $alias = drupal_lookup_path('source', $path, $path_language); //can't use drupal_get_normal_path, it calls custom_url_rewrite_inbound
+        if ($alias) 
+          $path = $alias;
       }
-      if ($app_nid = fb_settings(FB_SETTINGS_APP_NID)) {
-        if (count($args)) {
-          $path = implode('/', $args); // remaining args
-          $path = drupal_get_normal_path($path);
-        }
-        else
-          // frontpage
-          $path = drupal_get_normal_path(variable_get('site_frontpage', 'node'));
+      else {
+        // frontpage
+        $path = variable_get('site_frontpage', 'node');
+        $alias = drupal_lookup_path('source', $path, $path_language);
+        if ($alias) 
+          $path = $alias;
+        $_REQUEST['destination'] = $path; //required workaround for compatibility with Global Redirect module, best practice?
       }
-    } 
-  }
-  else if ($type == 'alias') {
-    $pre = '';
-    
-    // Prefix each known value to the URL
-    foreach ($prefixes as $prefix) {
-      if ($value = fb_settings($prefix))
-	$pre .= $prefix . '/'. $value . '/';
     }
-    $path  = $pre . $path;
+  }
+  else { //resolve aliases for non-fb-callbacks
+    $alias = drupal_lookup_path('source', $path, $path_language);
+    if ($alias) 
+      $path = $alias;
   }
   
-  return $path;  
+  $result = $path;
 }
 
 function fb_settings($key, $value = NULL) {
@@ -117,6 +144,17 @@ function fb_settings($key, $value = NULL
 }
 
 /**
+ * Returns a list of the values which we prepend to paths when rewriting urls.
+ */
+function _fb_settings_url_rewrite_prefixes() {
+  static $prefixes;
+  if (!isset($prefixes)) {
+    $prefixes = array(FB_SETTINGS_APP_NID, FB_SETTINGS_PAGE_TYPE, FB_SETTINGS_SESSION_KEY);
+  }
+  return $prefixes;
+}
+
+/**
  * Parse a setting from the URL.  This may be called before
  * custom_url_rewrite, so we can't count on fb_settings() to return the value.
  * For internal use only (see fb_session.inc).
@@ -139,5 +177,3 @@ function _fb_settings_parse($key) {
   }
 }
 
-
-?>
\ No newline at end of file
Index: fb_user.info
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_user.info,v
retrieving revision 1.2
diff -u -p -r1.2 fb_user.info
--- fb_user.info	5 Feb 2009 03:34:50 -0000	1.2
+++ fb_user.info	22 Feb 2009 20:13:04 -0000
@@ -1,5 +1,6 @@
 name= DFF User Management
 description = Create local accounts for users of Facebook Apps.
 package = Drupal for Facebook
-dependencies = fb fb_app
-
+dependencies[] = fb
+dependencies[] = fb_app
+core = 6.x
Index: fb_user.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_user.install,v
retrieving revision 1.3
diff -u -p -r1.3 fb_user.install
--- fb_user.install	20 May 2008 05:37:52 -0000	1.3
+++ fb_user.install	22 Feb 2009 20:13:04 -0000
@@ -1,39 +1,38 @@
 <?php
 
+/**
+ * Implementation of hook_install().
+ */
 function fb_user_install() {
-  global $db_type;
-  if ($db_type == 'mysqli' ||
-	  $db_type == 'mysql') {
-    $query[] = <<<QUERY
-CREATE TABLE IF NOT EXISTS {fb_user_app} (
-apikey varchar(128) NOT NULL,
-fbu int(11) unsigned NOT NULL,
-uid int(11) unsigned DEFAULT NULL,
-added int(4) unsigned NOT NULL,
-time_cron int(11) unsigned NOT NULL,
-time_access int(11) unsigned NOT NULL,
-session_key varchar(128) NOT NULL,
-session_key_expires int(11) unsigned NOT NULL,
-PRIMARY KEY (apikey, fbu),
-INDEX (uid),
-UNIQUE INDEX (uid, apikey)
-) /*!40100 DEFAULT CHARACTER SET UTF8 */;
-QUERY;
-  }
-  else {
-    // TODO: handle other databases
-    drupal_set_message(t('Unable to install fb_user database schema to a database of type: %type', array('%type' => $db_type)), 'error');
-  }
-  foreach ($query as $q) {
-    $status = db_query ($q);
-	if (!$status) {
-	  drupal_set_message(t('Error installing fb_user: %error %query', 
-						   array('%query' => '<pre>'.$q.'</pre>',
-								 '%error' => db_error())), 
-						 'error');
-	}
-  }
+  // Create tables.
+  drupal_install_schema('fb_user');
+}
+
+
+/**
+ * Implementation of hook_uninstall().
+ */
+function fb_user_uninstall() {
+  // Remove tables.
+  drupal_uninstall_schema('fb_user');
+}
+
+
+function fb_user_schema() {
+  $schema['fb_user_app'] = 
+    array('fields' => array('apikey' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+                            'fbu' => array('type' => 'int', 'length' => 11, 'unsigned' => TRUE, 'not null' => TRUE, ),
+                            'uid' => array('type' => 'int', 'size' => 'normal', 'not null' => TRUE, ),
+                            'added' => array('type' => 'int', 'length' => 4, 'unsigned' => TRUE, 'not null' => TRUE, ),
+                            'time_cron' => array('type' => 'int', 'length' => 11, 'unsigned' => TRUE, 'not null' => TRUE, ),
+                            'time_access' => array('type' => 'int', 'length' => 11, 'unsigned' => TRUE, 'not null' => TRUE, ),
+                            'session_key' => array('type' => 'varchar', 'length' => 128, 'not null' => TRUE, ),
+                            'session_key_expires' => array('type' => 'int', 'length' => 11, 'unsigned' => TRUE, 'not null' => TRUE, ),
+          ),
+          'primary key' => array('apikey', 'fbu'),
+    );
   
+  return $schema;
 }
 
 function fb_user_update_1() {
Index: fb_user.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/fb_user.module,v
retrieving revision 1.28
diff -u -p -r1.28 fb_user.module
--- fb_user.module	14 Jan 2009 22:56:33 -0000	1.28
+++ fb_user.module	22 Feb 2009 20:13:04 -0000
@@ -45,7 +45,7 @@ function _fb_user_track($fb, $fb_app, $u
   if (!$user->uid || $user->uid == $fb_user_data['not_logged_in_uid'] || $user->uid == $fb_user_data['logged_in_uid']) {
     $result =db_query("REPLACE INTO {fb_user_app} (apikey, fbu, added, time_access, session_key, session_key_expires) VALUES ('%s', %d, %d, %d, '%s', %d)",
                       $fb_app->apikey, fb_facebook_user(),
-                      $fb->api_client->users_isAppUser(), time(),
+                      fb_is_app_user($fb), time(),
                       $fb->api_client->session_key, $_REQUEST['fb_sig_expires']
     );
   }
@@ -54,7 +54,7 @@ function _fb_user_track($fb, $fb_app, $u
     $result =db_query("REPLACE INTO {fb_user_app} (apikey, fbu, uid, added, time_access, session_key, session_key_expires) VALUES ('%s', %d, %d, %d, %d, '%s', %d)",
                       $fb_app->apikey, fb_facebook_user(),
                       $user->uid,
-                      $fb->api_client->users_isAppUser(), time(),
+                      fb_is_app_user($fb), time(),
                       $fb->api_client->session_key, $_REQUEST['fb_sig_expires']
     );
   }
@@ -145,7 +145,7 @@ function fb_user_fb($op, $data, &$return
 
     // Check if we need to create a local account for this user.
     if (($fb_user_data['create_account'] == FB_USER_OPTION_CREATE_ADD &&
-	 $fb->api_client->users_isAppUser()) ||
+	 fb_is_app_user($fb)) ||
 	($fb_user_data['create_account'] == FB_USER_OPTION_CREATE_LOGIN)) {
       
       // Check if the local account is already made.
@@ -185,7 +185,7 @@ function fb_user_fb($op, $data, &$return
 	  (!$_REQUEST['fb_sig_in_profile_tab'])) {
 	
 	// Redirect to a canvas page
-	$url = fb_canvas_fix_url(url(fb_scrub_urls($_REQUEST['q']), NULL, NULL, TRUE), $fb_app);
+	$url = fb_canvas_fix_url(url(fb_scrub_urls($_REQUEST['q']), array('absolute' => TRUE)), $fb_app);
 	if (fb_verbose()) 
 	  watchdog('fb_debug', "User uid is now {$user->uid} (was {$original_uid}), redirecting to $url to ensure permissions are correct."); // debug
 	$fb->redirect($url);
@@ -194,21 +194,7 @@ function fb_user_fb($op, $data, &$return
     
     // Keep a record of when user accesses app, and whether they have added it.
     _fb_user_track($fb, $fb_app, $user);
-      
-    // We don't want user's who are not logged in (in the facebook sense) to
-    // login locally.  So let's make sure they've added the app before doing
-    // anything related to Drupal accounts.
-    /** I _think_ the new api no longer requires this.  TODO: confirm.
-    if (strpos($_GET['q'],'user/login') === 0) {
-      // Have to check idAppUser in case of iframe.
-      if (!$fb->api_client->users_isAppUser())
-        $fb->require_login();
-    }
-    else if (strpos($_GET['q'],'user/register') === 0) {
-      if (!$fb->api_client->users_isAppUser())
-        $fb->require_login();
-    }
-    */
+
     // Now do I need a goto or some such???
     
     // debug
@@ -286,7 +272,7 @@ function fb_user_authentication_is_requi
   }
 }
 
-function fb_user_form_alter($form_id, &$form) {
+function fb_user_form_alter(&$form, &$form_state, $form_id) {
   //drupal_set_message("fb_user_form_alter($form_id) " . dpr($form, 1));
   
   // Add our settings to the fb_app edit form.
@@ -565,7 +551,7 @@ function fb_user_user($op, &$edit, &$acc
       else {
         // Non-fbml page
         // TODO: use API to hide permissions we already have
-        $url = url($_GET['q'], NULL, NULL, TRUE);
+        $url = url($_GET['q'], array('absolute' => TRUE));
         $form[$key] =
           array('#type' => 'markup',
                 '#value' => l(t($t, array('%application' => $fb_app->title)),
@@ -699,7 +685,7 @@ function fb_user_create_local_user($fb, 
     
     $account = user_save('', $user_default);
 
-    watchdog('fb_user', t('New user: %name %email.', array('%name' => $name, '%email' => '<'. $mail .'>')), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));
+    watchdog('fb_user', 'New user: %name %email.', array('%name' => $name, '%email' => '<'. $mail .'>'), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));
 
     // Allow third-party modules to act after account creation.
     //$config = fb_invoke($fb_app, FB_OP_POST_USER, NULL, array('account' => $account));
@@ -710,8 +696,8 @@ function fb_user_create_local_user($fb, 
     // TODO: move this to fb_action.  Temporarily disabled.
     if (FALSE) {
       // Prepare to send an email.
-      $base = url('<front>', NULL, NULL, TRUE);
-      $variables = array('!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!password' => $user_default['pass'], '!uri' => $base, '!uri_brief' => substr($base, strlen('http://')), '!mailto' => $mail, '!date' => format_date(time()), '!login_uri' => url('user', NULL, NULL, TRUE), '!edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE), '!login_url' => user_pass_reset_url($account));
+      $base = url('<front>', array('absolute' => TRUE));
+      $variables = array('!username' => $account->name, '!site' => variable_get('site_name', 'Drupal'), '!password' => $user_default['pass'], '!uri' => $base, '!uri_brief' => substr($base, strlen('http://')), '!mailto' => $mail, '!date' => format_date(time()), '!login_uri' => url('user', array('absolute' => TRUE)), '!edit_uri' => url('user/'. $account->uid .'/edit', array('absolute' => TRUE)), '!login_url' => user_pass_reset_url($account));
       
       $subject = _user_mail_text('welcome_subject', $variables);
       $body = _user_mail_text('welcome_body', $variables);
@@ -847,5 +833,3 @@ function fb_user_token_values($type = 'a
   return $values;
 }
 
-
-?>
\ No newline at end of file
Index: themes/fb_fbml/fb_fbml.info
===================================================================
RCS file: themes/fb_fbml/fb_fbml.info
diff -N themes/fb_fbml/fb_fbml.info
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ themes/fb_fbml/fb_fbml.info	22 Feb 2009 20:13:04 -0000
@@ -0,0 +1,11 @@
+name = fb_fbml
+description = Use on Facebook FBML canvas pages only.
+core = 6.x
+engine = phptemplate
+
+regions[admin] = Admin sidebar
+regions[header] = Canvas Header
+regions[right] = Canvas Right
+regions[content_footer] = Content Footer
+regions[canvas_footer] = Canvas Footer
+
Index: themes/fb_fbml/node.tpl.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/themes/fb_fbml/node.tpl.php,v
retrieving revision 1.4
diff -u -p -r1.4 node.tpl.php
--- themes/fb_fbml/node.tpl.php	27 Mar 2008 22:13:43 -0000	1.4
+++ themes/fb_fbml/node.tpl.php	22 Feb 2009 20:13:04 -0000
@@ -10,6 +10,7 @@ if ($extra_style)
 ?>
 <div <?php print $class; ?> <?php print $style; ?>>
 
+<?php if ($picture || $page == 0 || $submitted || $about || $terms) { ?>
 <div class="node-header">
    <?php if ($picture && $submitted) {
   print $picture;
@@ -19,6 +20,7 @@ if ($extra_style)
 <span class="submitted"><?php print $submitted?></span>
 <span class="taxonomy"><?php print $terms?></span>
 </div>
+<?php } ?>
 <div class="content"><?php print $content?></div>
 <div class="footer">
   <?php if ($links) { ?><div class="links"><?php print $links?></div><?php }; ?>
Index: themes/fb_fbml/page.tpl.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/themes/fb_fbml/page.tpl.php,v
retrieving revision 1.7
diff -u -p -r1.7 page.tpl.php
--- themes/fb_fbml/page.tpl.php	15 Aug 2008 18:34:27 -0000	1.7
+++ themes/fb_fbml/page.tpl.php	22 Feb 2009 20:13:04 -0000
@@ -33,9 +33,9 @@
 </div>
 <?php endif; ?>
 </div>
-<?php if ($sidebar_right):?>
+<?php if ($right):?>
 <div id="sidebar-right" class="sidebar-right">
-   <?php print $sidebar_right; ?>
+   <?php print $right; ?>
 <?php print $admin /* Administrator only sidebar */?>
 </div>
 <?php endif; ?>
Index: themes/fb_fbml/styles_fbml.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/themes/fb_fbml/styles_fbml.css,v
retrieving revision 1.3
diff -u -p -r1.3 styles_fbml.css
--- themes/fb_fbml/styles_fbml.css	6 Nov 2008 20:20:27 -0000	1.3
+++ themes/fb_fbml/styles_fbml.css	22 Feb 2009 20:13:04 -0000
@@ -1,6 +1,6 @@
-  .page-wrap {
-  position: relative;
-  }
+.page-wrap {
+    position: relative;
+}
   .page-wrap.in-new-facebook { width: 760px; }
 
   div.error {
@@ -80,6 +80,7 @@
   
   .header ul.links, .header .block-menu {
   float: right;
+  clear: right;
 }
   
   .header .block .content {clear: none;}
@@ -150,17 +151,17 @@
 
   /* Give some links the facebook button look */
   a.fb_button {
-	background:#526EA6 url(http://www.facebook.com/images/pandemic/white_arrow_on_blue.gif) no-repeat scroll right center;
-	border-color:#145C9A rgb(14, 31, 91) rgb(14, 31, 91) rgb(20, 92, 154);
-	border-style:solid;
-	border-width:1px;
+    background:#526EA6 url(http://www.facebook.com/images/pandemic/white_arrow_on_blue.gif) no-repeat scroll right center;
+    border-color:#145C9A rgb(14, 31, 91) rgb(14, 31, 91) rgb(20, 92, 154);
+    border-style:solid;
+    border-width:1px;
     color:#FFFFFF;
     font-weight:bold;
     padding:3px 24px 5px 15px;
   }
   a.fb_button:hover {
     background-color:#40578A;
-	text-decoration:none;
+    text-decoration:none;
   }
 
   table {
Index: themes/fb_fbml/template.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fb/themes/fb_fbml/template.php,v
retrieving revision 1.13
diff -u -p -r1.13 template.php
--- themes/fb_fbml/template.php	12 Oct 2008 15:43:14 -0000	1.13
+++ themes/fb_fbml/template.php	22 Feb 2009 20:13:04 -0000
@@ -1,17 +1,48 @@
 <?php
 
+function fb_fbml_preprocess_page() {
+  dpm(func_get_args(), 'fb_fbml_preprocess_page');
+}
 
-function fb_fbml_page($content, $show_blocks = TRUE) {
-  $output = phptemplate_page($content, $show_blocks);
+function fb_fbml_page($content, $show_blocks = TRUE, $show_messages = TRUE) {
+  $variables = array('template_files' => array(),
+		     'content' => $content,
+		     'show_blocks' => $show_blocks,
+		     'show_messages' => $show_messages,
+		     );
+  $hook = 'page';
+  
+  // We have to go out of our way here to theme the tabs.
+  
+  // The code in menu.inc that themes them is complex,
+  // incomprehensible, and tangles the theme layer with the logic
+  // layer.  It doesn't help that the same theme functions are called
+  // for tabs as are called for all other menus.  So we use a global
+  // to keep track of what we're doing.
+  global $_fb_fbml_state;
+  $_fb_fbml_state = 'tabs';
+  // Why does a call to menu_tab_root_path theme the tabs?  I have no
+  // idea, but it does and caches the result.
+  menu_tab_root_path();
+  $_fb_fbml_state = NULL;
+  
+  template_preprocess($variables, $hook);
+  template_preprocess_page($variables, $hook);
+  // If any modules implement a preprocess function, they're SOL, we don't know about it.
+  
+  // Now our own preprocessing
+  fb_fbml_preprocess($variables, $hook);
+  
+  $template_file = path_to_theme() . '/page.tpl.php';
+  $output = theme_render_template($template_file, $variables);
   
   if (function_exists('fb_canvas_process')) {
     $output = fb_canvas_process($output);
   }
   return $output;
-  
 }
 
-function _phptemplate_variables($hook, $vars = array()) {
+function fb_fbml_preprocess(&$vars, $hook) {
   global $fb_app, $user;
   
   if ($hook == 'page') {
@@ -71,17 +102,17 @@ function _phptemplate_variables($hook, $
       
       // Style page differently depending on which sidebars are present.
       // Approach copied from Zen theme.
-      // allows advanced theming based on context (home page, node of certain type, etc.)
+      // allows styling based on context (home page, node of certain type, etc.)
       $body_classes = array();
       $body_classes[] = ($vars['is_front']) ? 'front' : 'not-front';
       $body_classes[] = ($user->uid > 0) ? 'logged-in' : 'not-logged-in';
-      if ($vars['sidebar_left'] && $vars['sidebar_right']) {
+      if ($vars['left'] && $vars['right']) {
 	$body_classes[] = 'with-both-sidebars';
       }
-      else if ($vars['sidebar_right']) {
+      else if ($vars['right']) {
 	$body_classes[] = 'with-sidebar-right';
       }
-      else if ($vars['sidebar_left']) {
+      else if ($vars['left']) {
 	$body_classes[] = 'with-sidebar-left';
       }
       
@@ -90,23 +121,22 @@ function _phptemplate_variables($hook, $
 	$body_classes[] = 'in-new-facebook';
       
       $vars['body_classes'] = implode(' ', $body_classes);
-      
     }
   }
   else if ($hook == 'node') {
     if ($vars['teaser']) {
       $vars['template_file'] = 'node-teaser';
     }
-    
+
     // TODO: could move this to phptemplate engine.
     if (count($vars['about']))
       $vars['about'] = drupal_render($vars['about']);
     if (count($vars['children']))
       $vars['children'] = drupal_render($vars['children']);
-    
+
     if ($vars['extra_style'])
       $vars['extra_style'] = drupal_render($vars['extra_style']);
-    
+
     if ($vars['teaser'])
       $size = 'thumb';
     else
@@ -116,7 +146,6 @@ function _phptemplate_variables($hook, $
     
     //drupal_set_message("node vars: " . dprint_r($vars, 1));
   }
-  return $vars;
 }
 
 function fb_fbml_regions() {
@@ -132,37 +161,64 @@ function fb_fbml_regions() {
 }
 
 //// tabs
+function fb_fbml_menu_local_task($link, $active = FALSE) {
+  global $_fb_fbml_state;
+
+  if ($_fb_fbml_state == 'tabs') {
+	if ($active) {
+	  $link = str_replace('selected="false"', 'selected="true"', $link);
+	}
+	return $link;
+  } 
+  else
+	return theme_menu_local_task($link, $active);
+}
+
+function fb_fbml_menu_item_link($link) {
+  global $_fb_fbml_state;
 
-function phptemplate_menu_local_tasks() {
+  if ($_fb_fbml_state == 'tabs') {
+	// Theme an FBML tab
+	$output .= "<fb:tab-item href=\"".url($link['href'])."\" title=\"".$link['title']."\" selected=\"false\">".$item['title']."</fb:tab-item>\n";
+	return $output;
+  }
+  else
+	return theme_menu_item_link($link, $active);
+}
+
+function fb_fbml_menu_local_tasks() {
   global $fb;
+  // Because menu.inc's navigation of the menu tree is too complicated
+  // to understand, or reproduce here, we need to maintain state as the
+  // menu tree is navigated.
+  global $_fb_fbml_state;
+  $_fb_fbml_state = 'argh';
+
   if ($fb && $fb->in_fb_canvas()) {
-    $local_tasks = menu_get_local_tasks();
-    $pid = menu_get_active_nontask_item();
     $output = '';
     
-    if (count($local_tasks[$pid]['children'])) {
-      $output .= "<fb:tabs>\n";
-      foreach ($local_tasks[$pid]['children'] as $mid) {
-	$item = menu_get_item($mid);
-	$selected = menu_in_active_trail($mid) ? "true" : "false";
-	$output .= "<fb:tab-item href=\"".url($item['path'], NULL, NULL, FALSE)."\" title=\"".$item['title']."\" selected=\"$selected\">".$item['title']."</fb:tab-item>\n";
-      }
-      $output .= "</fb:tabs>\n";
-	}
-    // TODO secondary local tasks
+    $_fb_fbml_state = 'primary';
+    if ($primary = menu_primary_local_tasks()) {
+      $output .= "<fb:tabs>\n". $primary ."</fb:tabs>\n";
+    }
+
+    $_fb_fbml_state = 'secondary';
+    
     if ($secondary = menu_secondary_local_tasks()) {
-	  $output .= "<ul class=\"tabs secondary\">\n". $secondary ."</ul>\n";
+      // TODO: use fbml for secondary tabs
+      $output .= "<ul class=\"tabs secondary\">\n". $secondary ."</ul>\n";
     }
+    $_fb_fbml_state = NULL;
+    
   }
-  else 
+  else {
     $output = theme_menu_local_tasks();
-  
+  }
   return $output;
-  
 }
 
 // collapsing fieldsets
-function phptemplate_fieldset($element) {
+function fb_fbml_fieldset($element) {
   global $fb;
   if (($fb && $fb->in_fb_canvas()) ||
       (function_exists('fb_canvas_is_fbml') && fb_canvas_is_fbml())) {
