diff --git a/fb.module b/fb.module
index bca07d7..0bdea25 100644
--- a/fb.module
+++ b/fb.module
@@ -499,6 +499,10 @@ function fb_graph($path, $params = array(), $method = 'GET', $fb = NULL) {
 
   if (isset($http->data)) {
     $data = json_decode($http->data, TRUE);
+    // Most times graph returns JSON, but other times query string.  Thanks Facebook!
+    if (!$data) {
+      parse_str($http->data, $data);
+    }
   }
   else {
     $data = array(); // avoid php warnings.
@@ -1017,10 +1021,10 @@ function fb_get_object_fbu($object) {
     // $object->init may be present when object is a user.
     $fbu = substr($object->init, 0, $pos);
   }
-  elseif ($pos = strpos($object->name, '@facebook')) {
+  elseif (!empty($object->name) && ($pos = strpos($object->name, '@facebook'))) {
     $fbu = substr($object->name, 0, $pos);
   }
-  elseif ($object->uid > 0) {
+  elseif (!empty($object->uid)) {
     // This can be expensive on pages with many comments or nodes!
     $fbu = fb_get_fbu($object->uid);
   }
diff --git a/fb_stream.admin.inc b/fb_stream.admin.inc
index 9a9dca2..541b1a6 100644
--- a/fb_stream.admin.inc
+++ b/fb_stream.admin.inc
@@ -20,6 +20,34 @@ function fb_stream_admin_settings() {
                              '%user_name' => $from['name'],
                              '%token' => $token,
                            )));
+      try {
+        $accounts = fb_graph('me/accounts', array('access_token' => $token));
+        if (!empty($accounts) && !empty($accounts['data'])) {
+          // TODO: support pagination if not all accounts returned.
+          $form['fb_stream_accounts'] = array(
+            '#title' => t('Additional Tokens'),
+            '#type' => 'fieldset',
+            '#collapsible' => TRUE,
+            '#description' => t('You may prefer one of the following tokens, to limit posting only to a single page.  If so, copy and paste the token into the form field below.'),
+          );
+          // TODO: perhaps a radio button would be better then forcing user to copy and paste.
+          foreach ($accounts['data'] as $account_data) {
+            $rows[] = array(t('%fb_page_title (%fb_page_type)', array(
+                                '%fb_page_title' => $account_data['name'],
+                                '%fb_page_type' => $account_data['category'],
+                              )),
+                            $account_data['access_token'],
+            );
+          }
+          $form['fb_stream_accounts']['detail'] = array(
+            '#type' => 'markup',
+            '#value' => theme('table', array(t('Page'), t('Access token')), $rows), // in D6, use '#value'!
+          );
+        }
+      }
+      catch (Exception $e) {
+        // If me/accounts fails, it probably just means the token is already an account token and not a user token.  Nothing to do here.
+      }
     }
     catch (Exception $e) {
       fb_log_exception($e, t('Unable to query graph with fb_stream token.'));
@@ -31,7 +59,7 @@ function fb_stream_admin_settings() {
 
   if (!empty($_REQUEST['code']) && empty($_POST)) {
     // Send user to this URL after token is generated.
-    $redirect_uri = url($_REQUEST['q'], array(
+    $redirect_uri = url(implode('/', arg()), array(
                           'absolute' => TRUE,
                           'query' => array(
                             'client_id' => $_REQUEST['client_id'],
@@ -39,7 +67,12 @@ function fb_stream_admin_settings() {
                         ));
 
     $token = fb_stream_admin_code_to_token($_REQUEST['code'], $_REQUEST['client_id'], $redirect_uri);
-    drupal_set_message(t('Generated a new access token %token.  Note you must press the save button to use this value!', array('%token' => $token)), 'warning');
+    if ($token) {
+      drupal_set_message(t('Generated a new access token, but not yet saved, %token .  Note you must press the save button to use this value!', array('%token' => $token)), 'warning');
+    }
+    else {
+      drupal_set_message(t('Failed to generate a token from code returned by facebook.'), 'warning');
+    }
   }
 
   $form['fb_stream_token'] = array(
@@ -52,6 +85,14 @@ function fb_stream_admin_settings() {
     '#required' => TRUE,
   );
 
+  $form['fb_stream_token_prefer_long'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Prefer longer-lived tokens.'),
+    '#description' => t('Generate a longer-lived token if possible.'),
+    '#default_value' => variable_get('fb_stream_token_prefer_long', TRUE),
+  );
+
+
   // TODO: show user what permissions and pages their token can access.
 
   $form['fb_stream_apps'] = array(
@@ -61,12 +102,13 @@ function fb_stream_admin_settings() {
   );
   foreach (fb_get_all_apps() as $fb_app) {
     // Send user to this URL after token is generated.
-    $redirect_uri = url($_REQUEST['q'], array(
+    $redirect_uri = url(implode('/', arg()), array(
                           'absolute' => TRUE,
                           'query' => array(
                             'client_id' => $fb_app->id,
                           ),
                         ));
+
     $form['fb_stream_apps'][$fb_app->id] = array(
       '#type' => 'markup',
       '#value' => l(t('post via the %title application', array(
@@ -84,9 +126,60 @@ function fb_stream_admin_settings() {
     );
   }
 
+  // Our validate hook gives us a way to swap long-lived tokens for shorter ones.
+  $form['#validate'][] = '_fb_stream_validate_token';
+
   return system_settings_form($form);
 }
 
+function _fb_stream_validate_token($form, &$form_state) {
+  $values = $form_state['values'];
+  $token = $values['fb_stream_token'];
+  try {
+    $via = fb_graph('app', array('access_token' => $token));
+
+    if ($values['fb_stream_token_prefer_long']) {
+      $app = fb_get_app(array('id' => $via['id']));
+
+      if ($app && $app->secret) {
+        try {
+          $result = fb_graph('oauth/access_token', array(
+                               'client_id' => $app->id,
+                               'client_secret' => $app->secret,
+                               'grant_type' => 'fb_exchange_token',
+                               'fb_exchange_token' => $token,
+                             ));
+          if (!empty($result['access_token'])) {
+            if ($result['access_token'] != $token) {
+              form_set_value('fb_stream_token', $result['access_token']);
+              drupal_set_message(t('Replaced access token with %token , set to expire in %duration.', array(
+                                     '%token' => $result['access_token'],
+                                     '%duration' => format_interval($result['expires']),
+                                   )));
+            }
+            else {
+              drupal_set_message(t('Token is long-lived, set to expire in %duration.', array(
+                                     '%token' => $result['access_token'],
+                                     '%duration' => format_interval($result['expires']),
+                                   )));
+            }
+          }
+        }
+        catch (Exception $e) {
+          // This is reached whenever token belongs to an account instead of a user.  So we don't need to be verbose about it.
+          drupal_set_message(t('Could not convert the token into a longer-lived token.  This is expected when token belongs to a page rather than a user.'));
+          //fb_log_exception($e, t('Failed to convert token to longer-lived token.'));
+        }
+      }
+    }
+  }
+  catch (Exception $e) {
+    fb_log_exception($e, t('Unable to validate fb_stream token.'));
+    form_set_error('fb_stream_token', $e->getMessage());
+  }
+}
+
+
 function fb_stream_admin_code_to_token($code, $app_id, $redirect_uri) {
   $fb_app = fb_get_app(array('id' => $app_id));
   $path = url("https://graph.facebook.com/oauth/access_token", array(
@@ -98,13 +191,9 @@ function fb_stream_admin_code_to_token($code, $app_id, $redirect_uri) {
                 ),
               ));
   $http = drupal_http_request($path);
-
   if ($http->code == 200 && isset($http->data)) {
-    $data = explode('=', $http->data);
-    $token = $data[1];
-    if ($token) {
-      return $token;
-    }
+    $data = array();
+    parse_str($http->data, $data);
+    return $data['access_token'];
   }
 }
-
