diff --git a/fboauth.install b/fboauth.install
index 0e48b09..bfd8cc0 100644
--- a/fboauth.install
+++ b/fboauth.install
@@ -22,7 +22,12 @@ function fboauth_install() {
 function fboauth_uninstall() {
   drupal_uninstall_schema('fboauth');
   variable_del('fboauth_id');
+  variable_del('fboauth_apiversion');
   variable_del('fboauth_secret');
+  variable_del('fboauth_debug');
+  variable_del('fboauth_popup');
+  variable_del('fboauth_always_load_js');
+  variable_del('fboauth_anon_connect');
   variable_del('fboauth_user_email');
   variable_del('fboauth_user_username');
   variable_del('fboauth_user_picture');
@@ -82,3 +87,73 @@ function _fboauth_change_user_mail_field($action = 'install') {
   db_change_field($res, 'users', 'mail', 'mail', $schema['users']['fields']['mail']);
   return $res;
 }
+
+/**
+ * FBAPI v2.0: Remove deprecated user_checkins permission.
+ */
+function fboauth_update_6201() {
+  if ($connections = variable_get('fboauth_user_connections', array())) {
+    $deprecated = array(
+      'checkins',
+    );
+
+    foreach ($deprecated as $permission) {
+      $permission_key = array_search($permission, $connections);
+      if (is_numeric($permission_key)) {
+        unset($connections[$permission_key]);
+      }
+    }
+
+    variable_set('fboauth_user_connections', $connections);
+  }
+}
+
+/**
+ * FBAPI v2.3: Remove deprecated user_interests and user_activities permissions.
+ */
+function fboauth_update_6202() {
+  if ($connections = variable_get('fboauth_user_connections', array())) {
+    $deprecated = array(
+      'activities',
+      'interests',
+    );
+
+    foreach ($deprecated as $permission) {
+      $permission_key = array_search($permission, $connections);
+      if (is_numeric($permission_key)) {
+        unset($connections[$permission_key]);
+      }
+    }
+
+    variable_set('fboauth_user_connections', $connections);
+  }
+}
+
+/**
+ * FBAPI v2.0: Username deprecated. Use Real name for user name import.
+ */
+function fboauth_update_6203() {
+  if (variable_get('fboauth_user_username', 'name') == 'username') {
+    variable_set('fboauth_user_username', 'name');
+  }
+}
+
+/**
+ * FBAPI v2.0: Remove access to notes.
+ */
+function fboauth_update_6204() {
+  if ($connections = variable_get('fboauth_user_connections', array())) {
+    $deprecated = array(
+      'notes',
+    );
+
+    foreach ($deprecated as $permission) {
+      $permission_key = array_search($permission, $connections);
+      if (is_numeric($permission_key)) {
+        unset($connections[$permission_key]);
+      }
+    }
+
+    variable_set('fboauth_user_connections', $connections);
+  }
+}
diff --git a/fboauth.module b/fboauth.module
index 7e5957f..6305fb8 100644
--- a/fboauth.module
+++ b/fboauth.module
@@ -20,7 +20,7 @@ function fboauth_menu() {
     'type' => MENU_CALLBACK,
   );
   $items['admin/settings/fboauth'] = array(
-    'title' => t('Facebook OAuth settings'),
+    'title' => 'Facebook OAuth settings',
     'page callback' => 'drupal_get_form',
     'page arguments' => array('fboauth_settings_form'),
     'access arguments' => array('administer users'),
@@ -29,7 +29,7 @@ function fboauth_menu() {
     'type' => MENU_NORMAL_ITEM,
   );
   $items['user/%user/fboauth'] = array(
-    'title' => t('Facebook settings'),
+    'title' => 'Facebook settings',
     'page callback' => 'fboauth_user_form',
     'page arguments' => array(1),
     'access callback' => 'user_edit_access',
@@ -40,6 +40,39 @@ function fboauth_menu() {
 }
 
 /**
+ * Implements hook_init().
+ */
+function fboauth_init() {
+  global $user;
+  if (variable_get('fboauth_always_load_js', 0)) {
+    $url = array();
+    $parts = parse_url(request_uri());
+    $url['path'] = substr($parts['path'], 1);
+    if (isset($parts['query'])) {
+      parse_str($parts['query'], $url['query']);
+      if (isset($url['query']['q'])) {
+        $url['path'] = $url['query']['q'];
+        unset($url['query']['q']);
+      }
+    }
+
+    if (drupal_match_path($url['path'], '/user/' . $user->uid . '/fboauth')) {
+      $fbid = fboauth_fbid_load($user->uid);
+      if ($fbid !== FALSE) {
+        // We have a fbid so must be displaying the deauth button, no need for
+        // the popup window.
+      }
+      else {
+        drupal_add_js(drupal_get_path('module', 'fboauth') . '/fboauth_popup.js');
+      }
+    }
+    elseif (!drupal_match_path($url['path'], '/user/' . $user->uid . '/fboauth')) {
+      drupal_add_js(drupal_get_path('module', 'fboauth') . '/fboauth_popup.js');
+    }
+  }
+}
+
+/**
  * Implements hook_theme().
  */
 function fboauth_theme() {
@@ -80,6 +113,9 @@ function fboauth_block_info() {
   $blocks['login'] = array(
     'info' => t('Facebook login'),
   );
+  $blocks['connect'] = array(
+    'info' => t('Facebook connect'),
+  );
   return $blocks;
 }
 
@@ -90,8 +126,13 @@ function fboauth_block_view($delta) {
   $block = array();
   if (variable_get('fboauth_id', '') && !fboauth_fbid_load()) {
     // Set the redirect to the current page (unless we're on the login page).
-    $redirect = (arg(0) === 'user' && (arg(1) === 'login' || arg(1) == '')) ? NULL : $_GET['q'];
+    $destination = drupal_get_destination();
+    $redirect = (arg(0) === 'user' && (arg(1) === 'login' || arg(1) == '')) ? NULL : $destination['destination'];
     $block['content'] = fboauth_action_display('connect', $redirect);
+
+    if (variable_get('fboauth_popup', 1) && !variable_get('fboauth_always_load_js', 0)) {
+      drupal_add_js(drupal_get_path('module', 'fboauth') . '/fboauth_popup.js');
+    }
   }
   return $block;
 }
@@ -150,11 +191,23 @@ function fboauth_form_user_profile_form_alter(&$form, &$form_state) {
     '#type' => 'item',
     '#title' => t('Facebook connect'),
     '#children' => theme('fboauth_user_form_connect', $uid, $fbid),
+    '#after_build' => array('fboauth_form_user_profile_form_after_build'),
   );
 
   // The account settings move around in this form.
   $account_form = isset($form['account']) ? $form['account'] : $form;
 
+  // If a user has created/linked an account through a Facebook login, remove
+  // the current password field until they set a password.
+  // See http://drupal.org/node/1398782.
+  if ($fbid && $form['#user']->pass == '') {
+    if (empty($form_state['input'])) {
+      drupal_set_message(t('Please set a password to secure your account details.'), 'warning', FALSE);
+    }
+    unset($account_form['current_pass']);
+    $account_form['current_pass_required_values']['#value'] = array();
+  }
+
   // Inject the Facebook options after the e-mail settings. No weights are on
   // these elements by default, so we have to put it in order.
   $temp_form = array();
@@ -179,6 +232,15 @@ function fboauth_form_user_profile_form_alter(&$form, &$form_state) {
 }
 
 /**
+ * Addd the JS popup for the form if needed
+ */
+function fboauth_form_user_profile_form_after_build(){
+  if (variable_get('fboauth_popup', 1) && !variable_get('fboauth_always_load_js', 0)) {
+    drupal_add_js(drupal_get_path('module', 'fboauth') . '/fboauth_popup.js');
+  }
+}
+
+/**
  * Implements hook_fboauth_actions().
  */
 function fboauth_fboauth_actions() {
@@ -283,6 +345,28 @@ function fboauth_save($uid, $fbid) {
   if (!empty($fbid)) {
     db_query('INSERT INTO {fboauth_users} (uid, fbid) VALUES (%d, %d)', $uid, $fbid);
   }
+  $loggedin_account = user_load($uid); // load user, all user fields & fbuid
+  // Check if the logged in user has a picture saved & has linked their FB account through fboauth, but only if
+  // the site is configured to do this.
+  if (variable_get('fboauth_user_picture', 'picture') == 'picture' && is_null($loggedin_account->picture) && !empty($fbid)) {
+    $path = file_create_path('pictures');
+    file_check_directory($path, FILE_CREATE_DIRECTORY);
+    $picture_result = drupal_http_request('https://graph.facebook.com/' . variable_get('fboauth_apiversion', 'v2.3') . '/' . $fbid . '/picture?type=large');
+    $picture_path = $path . '/picture-' . $loggedin_account->uid . '.jpg';
+    $file = fopen($picture_path, 'w');
+    fwrite($file, $picture_result->data);
+    fclose($file);
+
+    // Check to make sure the picture isn't too large for the site settings.
+    $picture_info = image_get_info($picture_path);
+    list($max_dimensions['width'], $max_dimensions['height']) = explode('x', variable_get('user_picture_dimensions', '85x85'));
+    if (image_get_toolkit() && $picture_info['width'] > $max_dimensions['width'] || $picture_info['height'] > $max_dimensions['height']) {
+      image_scale($picture_path, $picture_path, $max_dimensions['width'], $max_dimensions['height']);
+    }
+
+    // Update the database record.
+    db_query("UPDATE {users} SET picture = '%s' WHERE uid = %d", $picture_path, $loggedin_account->uid);
+  }
 }
 
 /**
@@ -355,9 +439,15 @@ function fboauth_action_link_properties($action_name, $redirect = NULL, $app_id
       'client_id' => $app_id,
       'redirect_uri' => fboauth_action_url('fboauth/' . $action_name, array('absolute' => TRUE, 'query' => $query)),
     ),
-    'href' => 'https://www.facebook.com/dialog/oauth',
+    'href' => 'https://www.facebook.com/' . variable_get('fboauth_apiversion', 'v2.3') . '/dialog/oauth',
+    'attributes' => array(),
   );
 
+  if (variable_get('fboauth_popup', 1)) {
+    $return['attributes']['class'] = 'fboauth-popup';
+    $return['query']['display'] = 'popup';
+  }
+
   if ($permissions) {
     $return['query']['scope'] = implode(',', $permissions);
   }
@@ -421,7 +511,7 @@ function theme_fboauth_action($action, $link) {
  */
 function theme_fboauth_action__connect($action, $link) {
   $url = url($link['href'], array('query' => $link['query']));
-  $link['attributes']['class'] = isset($link['attributes']['class']) ? $link['attributes']['class'] : 'facebook-action-connect';
+  $link['attributes']['class'] = (isset($link['attributes']['class']) ? $link['attributes']['class'] . ' ' : '') . 'facebook-action-connect';
   $link['attributes']['rel'] = 'nofollow';
   $attributes = isset($link['attributes']) ? drupal_attributes($link['attributes']) : '';
   $title = isset($link['title']) ? check_plain($link['title']) : '';
diff --git a/fboauth_popup.js b/fboauth_popup.js
new file mode 100644
index 0000000..5f8ac61
--- /dev/null
+++ b/fboauth_popup.js
@@ -0,0 +1,38 @@
+(function ($) {
+
+  /**
+   * Add Drupal behaviors
+   */
+  Drupal.behaviors.fboauthPopup = function(context) {
+    /**
+     * modify Facbook Oauth (fboauth) button with class "facebook-action-connect"
+     * to open in a popup window, instead of using the current window.
+     * References:
+     * http://thinkdiff.net/facebook/create-facebook-popup-authentication-window-using-php-and-javascript/
+     * http://developers.facebook.com/docs/authentication/
+     * http://developers.facebook.com/docs/authentication/server-side/
+     * http://developers.facebook.com/docs/reference/dialogs/oauth/
+     */
+	 
+    //$('.fboauth-popup').click(function() {
+    $('.facebook-action-connect').click(function() {
+      var screenX    = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft,
+        screenY      = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop,
+        outerWidth   = typeof window.outerWidth != 'undefined' ? window.outerWidth : document.body.clientWidth,
+        outerHeight  = typeof window.outerHeight != 'undefined' ? window.outerHeight : (document.body.clientHeight - 22),
+        width    = 500,
+        height   = 270,
+        left     = parseInt(screenX + ((outerWidth - width) / 2), 10),
+        top      = parseInt(screenY + ((outerHeight - height) / 2.5), 10),
+        features = 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top;
+
+      var popupWindow = window.open($(this).attr("href"), 'fboauth', features);
+      if (window.focus) {
+        popupWindow.focus();
+      }
+
+      return false;
+    });
+  };
+
+})(jQuery);
\ No newline at end of file
diff --git a/includes/fboauth.fboauth.inc b/includes/fboauth.fboauth.inc
index 4af9909..194d8fd 100644
--- a/includes/fboauth.fboauth.inc
+++ b/includes/fboauth.fboauth.inc
@@ -29,9 +29,21 @@ function fboauth_action_page($action) {
     watchdog('fboauth', 'A Facebook login was attempted but could not be processed because the module is not yet configured. Vist the <a href="!url">Facebook OAuth configuration</a> to set up the module.', array('!url' => url('admin/settings/fboauth')));
   }
   elseif (isset($_REQUEST['error'])) {
-    $link = fboauth_action_link_properties($action_name, $app_id);
+    $url = !$user->uid ? url('<front>', array('absolute' => TRUE)) : url("user/{$user->uid}/edit", array('absolute' => TRUE));
+    $link = fboauth_action_link_properties($action_name, $url, $app_id);
     watchdog('fboauth', 'A user refused to allow access to the necessary Facebook information (@permissions) to login to the site.', array('@permissions' => $link['query']['scope']));
-    $error_message = t('This site requires access to information in order to log you into the site. If you like you can <a href="!facebook">sign in with Facebook again</a> or <a href="!register">register normally</a>.', array('!facebook' => url($link['href'], array('query' => $link['query'])), '!register' => url('user/register')));
+    $html_class = variable_get('fboauth_popup', 1) ? ' class="fboauth-popup"' : '';
+    $error_message = t('This site requires access to information in order to log you into the site. If you like you can <a href="!facebook"' . $html_class . '>sign in with Facebook again</a> or <a href="!register">register normally</a>.', array('!facebook' => url($link['href'], array('query' => $link['query'])), '!register' => url('user/register')));
+
+    drupal_set_message($error_message, 'error');
+
+    if (variable_get('fboauth_popup', 1)) {
+      // Close the popup and set the parent window to the target destination.
+      print fboauth_close_popup_window($url);
+      module_invoke_all('exit');
+      exit;
+    }
+    drupal_goto($url);
   }
   elseif (!isset($_REQUEST['code'])) {
     watchdog('fboauth', 'A Facebook request code was expected but no authorization was received.');
@@ -42,7 +54,16 @@ function fboauth_action_page($action) {
     if (empty($destination)) {
       $destination = isset($_REQUEST['destination']) ? $_REQUEST['destination'] : '<front>';
     }
-    drupal_goto($destination);
+    if (variable_get('fboauth_popup', 1)) {
+      // Close the popup and set the parent window to the target destination.
+      $url = !isset($user->pass) || $user->pass == '' ? url("user/{$user->uid}/edit", array('absolute' => TRUE)) : url($destination);
+      print fboauth_close_popup_window($url);
+      module_invoke_all('exit');
+      exit;
+    }
+    else {
+      drupal_goto($destination);
+    }
   }
 
   // In the event of an error, we stay on this page.
@@ -50,6 +71,29 @@ function fboauth_action_page($action) {
 }
 
 /**
+ * Returns a HTML string to close the popup modal window and redirect the opener window to the relevant URL.
+ *
+ * @param $url
+ * @return string
+ */
+function fboauth_close_popup_window($url) {
+  return "
+    <html>
+    <head>
+      <script type=\"text/javascript\">
+      if (window.opener) {"
+      . (isset($_REQUEST['error']) ? '' : "window.opener.location = '$url';") .
+        "setTimeout(function(){ window.close(); }, 500);
+      }
+      else {
+        window.location = '$url';
+      }
+      </script>
+    </head>
+    </html>";
+}
+
+/**
  * Invoke an action specified through hook_fboauth_action_info().
  */
 function fboauth_action_invoke($action_name, $app_id, $access_token) {
@@ -71,52 +115,147 @@ function fboauth_action_invoke($action_name, $app_id, $access_token) {
 function fboauth_action_connect($app_id, $access_token) {
   global $user;
 
-  $fbuser = fboauth_graph_query('me', $access_token);
-  $uid = fboauth_uid_load($fbuser->id);
+  // Save access_token in session for future use.
+  $_SESSION['fboauth']['access_token'] = $access_token;
 
-  // If the user has logged in before, load their account and login.
-  if (!$user->uid && $uid && ($account = user_load($uid))) {
-    fboauth_login_user($account);
+  $id = 'me'; // Versions prior to v2.4 and v2.5 are working with just this.
+  if (variable_get('fboauth_apiversion', 'v2.3') == 'v2.5'
+   || variable_get('fboauth_apiversion', 'v2.3') == 'v2.4') {
+    $id .= '?fields=email,name,first_name,last_name,age_range,link,gender,locale,timezone,updated_time,verified,birthday,location';
   }
-  // If the Facebook e-mail address matches an existing account, bind them
-  // together and log in as that account.
-  elseif (!empty($fbuser->email) && ($account = user_load(array('mail' => $fbuser->email)))) {
-    fboauth_save($account->uid, $fbuser->id);
 
-    // Logins will be denied if the user's account is blocked.
-    if ($user->uid || fboauth_login_user($account)) {
-      drupal_set_message(t('You\'ve connected your account with Facebook.'));
-    }
+  $fbuser = fboauth_graph_query($id, $access_token);
+
+  if (variable_get('fboauth_debug', '') == 1) {
+    watchdog('debug', '<pre>fbuser=' . print_r($fbuser, TRUE) . '</pre>');
   }
-  else {
-    // If the user is already logged in, associate the two accounts.
-    if ($user->uid) {
-      fboauth_save($user->uid, $fbuser->id);
-      drupal_set_message(t('You\'ve connected your account with Facebook.'));
+
+  // Use fake email if user email not available.
+  if (empty($fbuser->email)) {
+    $fbuser->email = $fbuser->id . '@facebook.com';
+  }
+
+  $uid = fboauth_uid_load($fbuser->id);
+  // If the user isn't logged in.
+  if (!$user->uid) {
+    // See if they are connected to FB & is an association between FB & Drupal.
+    if ($uid && ($account = user_load($uid))) {
+      fboauth_login_user($account);
     }
-    // Register a new user only if allowed.
-    elseif (variable_get('user_register', 1)) {
-      $account = fboauth_create_user($fbuser);
-      // Load the account fresh just to have a fully-loaded object.
-      $account = user_load($account->uid);
-
-      // If the account requires administrator approval the new account will
-      // have a status of '0' and not be activated yet.
-      if ($account->status == 0) {
-        _user_mail_notify('register_pending_approval', $account);
-        drupal_set_message(t('An account has been created for you on @sitename but an administrator needs to approve your account. In the meantime, a welcome message with further instructions has been sent to your e-mail address.', array('@sitename' => variable_get('site_name', ''))));
+    // No association between FB & this Drupal site, yet.
+    // So lets check & see if the FB address matches a Drupal email address.
+    else {
+      if (!empty($fbuser->email)) {
+        $account = NULL;
+
+        // Check and see if multiple_email module is in use.
+        if (module_exists('multiple_email')) {
+          if ($multiple_email_object = multiple_email_find_address($fbuser->email)) {
+            $account = user_load($multiple_email_object->uid);
+            if ($multiple_email_object->confirmed) {
+              // we're good
+            }
+            else {
+              // note:  drupal security team doesn't consider it a vulnerabilty that UID is publicly available
+              // https://www.drupal.org/node/1004778
+              drupal_set_message(t("We found your e-mail @email in the @sitename system, but it hasn't been confirmed. " .
+                      'Please <a href="!login">login manually</a> and then <a href="!edit">' .
+                      'resend your confirmation code</a> to confirm that you are the owner of this email address. This is required before you can connect to the site from Facebook with it.', array(
+                '@email' => $fbuser->email,
+                '@sitename' => variable_get('site_name', ''),
+                '!login' => url('user/login'),
+                '!edit' => url('user/' . $account->uid . '/edit/email-addresses'))));
+              return;
+            }
+          }
+          else {
+            // Email address not found in System
+          }
+        }
+        else {
+          // Just use the e-mail from the users table.
+          $account = user_load_by_mail($fbuser->email);
+        }
+        // If the Facebook e-mail address matches an existing account, bind them
+        // together and log in as that account.
+        if ($account) {
+          // Connect the account only if we allow anonymous users to connect accounts that have
+          // never been connected before.
+          if (variable_get('fboauth_anon_connect', TRUE)) {
+            // Logins will be denied if the user's account is blocked.
+            if (fboauth_login_user($account)) {
+              fboauth_save($account->uid, $fbuser->id);
+              drupal_set_message(t("You've connected your account with Facebook."));
+            }
+          }
+          else {
+            drupal_set_message(t('We found your e-mail @email in the @sitename system, but the account has never been connected to Facebook before. ' .
+                    'Please <a href="!login">login manually</a> and <a href="!edit">connect to Facebook</a> while logged in. ' .
+                    'Once you have completed this step, you may login through Facebook whenever you like.', array(
+              '@email' => $fbuser->email,
+              '@sitename' => variable_get('site_name', ''),
+              '!login' => url('user/login'),
+              '!edit' => url('user/' . $account->uid . '/edit'))));
+          }
+        }
+        // Register a new user only if allowed.
+        elseif (variable_get('user_register', 1)) {
+          $account = fboauth_create_user($fbuser);
+
+          if (!isset($account) || empty($account)) {
+            drupal_set_message(t('Unable to create a new account using your Facebook profile.'), 'warning');
+            return;
+          }
+
+          // Load the account fresh just to have a fully-loaded object.
+          $account = user_load($account->uid);
+
+          // If the account requires administrator approval the new account will
+          // have a status of '0' and not be activated yet.
+          if ($account->status == 0) {
+            _user_mail_notify('register_pending_approval', $account);
+            drupal_set_message(
+                t('An account has been created for you on @sitename but an ' .
+                    'administrator needs to approve your account. In the meantime, ' .
+                    'a welcome message with further instructions has been sent ' .
+                    'to your e-mail address.', array(
+              '@sitename' => variable_get('site_name', ''))));
+          }
+          // Log in the user if no approval is required.
+          elseif (fboauth_login_user($account)) {
+            drupal_set_message(t('Welcome to @sitename. ' .
+                    'Basic information has been imported from Facebook into your account. ' .
+                    'You may want to <a href="!edit">edit your account</a> to confirm the ' .
+                    'details and set a password.', array(
+              '@sitename' => variable_get('site_name', ''),
+              '!edit' => url('user/' . $account->uid . '/edit'))));
+          }
+          // If the login fails, fboauth_login_user() throws an error message.
+        }
+        // Since user's can't create new accounts on their own, show an error.
+        else {
+          drupal_set_message(t('Your Facebook e-mail address does not match
+            any existing accounts. If you have an account, you must first
+            log in before you can connect your account to Facebook.
+            Creation of new accounts on this site is disabled.'));
+        }
       }
-      // Log in the user if no approval is required.
-      elseif (fboauth_login_user($account)) {
-        drupal_set_message(t('Welcome to @sitename. Basic information has been imported from Facebook into your account. You may want to <a href="!edit">edit your account</a> to confirm the details and set a password.', array('@sitename' => variable_get('site_name', ''), '!edit' => url('user/' . $account->uid . '/edit'))));
+      // Email not provided by Facebook.
+      else {
+        drupal_set_message(t("Facebook didn't provide an e-mail address " .
+                "to be associated with your account, so we can't compare it " .
+                "with the e-mail addresses in this system."));
+        return;
       }
-      // If the login fails, fboauth_login_user() throws its own error message.
-    }
-    // Since user's can't create new accounts on their own, show an error.
-    else {
-      drupal_set_message(t('Your Facebook e-mail address does not match any existing accounts. If you have an account, you must first log in before you can connect your account to Facebook. Creation of new accounts on this site is disabled.'));
+      // Done if no e-mail address provided by facebook.
     }
   }
+  else {
+    // The user is already logged in to Drupal.
+    // So just associate the two accounts.
+    fboauth_save($user->uid, $fbuser->id);
+    drupal_set_message(t("You've connected your account with Facebook."));
+  }
 }
 
 /**
@@ -126,10 +265,10 @@ function fboauth_action_deauth($app_id, $access_token) {
   global $user;
 
   // Deauthorize our application from Facebook.
-  $result = fboauth_method_invoke('auth.revokeAuthorization', $access_token);
+  $result = fboauth_graph_query('me/permissions', $access_token, array(), 'DELETE');
 
   // If successful, also remove the uid-fbid pairing.
-  if (!is_array($result) && $result) {
+  if (isset($result->success) && $result->success) {
     $fbid = fboauth_fbid_load($user->uid);
     fboauth_save($user->uid, NULL);
 
@@ -156,15 +295,19 @@ function fboauth_create_user($fbuser, $options = array()) {
   );
   $options += $defaults;
 
-  // Use their Facebook user name (if defined), otherwise their real name.
+  // Depending on settings use profile id or real name for drupal username.
+  switch ($options['username']) {
+    case 'name':
+      $username = $fbuser->name;
+      break;
+
+    case 'id':
+      $username = $fbuser->id;
+      break;
+  }
+
   // If an account already exists with that name, increment until the namespace
   // is available.
-  if ($options['username'] === 'username' && !empty($fbuser->username)) {
-    $username = $fbuser->username;
-  }
-  else {
-    $username = $fbuser->name;
-  }
   $query = "SELECT uid FROM {users} WHERE name = '%s'";
   $uid = db_result(db_query($query, $username));
   $i = 0;
@@ -180,8 +323,10 @@ function fboauth_create_user($fbuser, $options = array()) {
   $edit = array(
     'name' => $username,
     'mail' => !empty($fbuser->email) ? $fbuser->email : '',
+    'init' => !empty($fbuser->email) ? $fbuser->email : '',
     // If user_register is "1", then no approval required.
     'status' => $options['status'],
+    'timezone' => variable_get('date_default_timezone'),
     'fboauth' => TRUE, // Signify this is being imported by Facebook OAuth.
     'fboauth_fbid' => $fbuser->id, // So that other modules can load the account.
   );
@@ -198,13 +343,27 @@ function fboauth_create_user($fbuser, $options = array()) {
     $function($edit, $fbuser);
   }
 
+  // check for a valid email address and username and if they don't exist return NULL
+  if (!isset($edit) || empty($edit)) {
+    watchdog('fboauth', 'Account information not provided.');
+    return NULL;
+  }
+  if (!isset($edit['mail']) || empty($edit['mail'])) {
+    watchdog('fboauth', 'Email address not provided by Facebook.');
+    return NULL;
+  }
+  if (!isset($edit['name']) || empty($edit['name'])) {
+    watchdog('fboauth', 'Username not able to be retrieved from Facebook or be generated.');
+    return NULL;
+  }
+
   $account = user_save(NULL, $edit);
 
   // Retrieve the user's picture from Facebook and save it locally.
   if ($account->uid && $options['picture'] === 'picture') {
     $path = file_create_path('pictures');
     file_check_directory($path, FILE_CREATE_DIRECTORY);
-    $picture_result = drupal_http_request('https://graph.facebook.com/' . $fbuser->id . '/picture?type=large');
+    $picture_result = drupal_http_request('https://graph.facebook.com/' . variable_get('fboauth_apiversion', 'v2.3') . '/'. $fbuser->id . '/picture?type=large');
     $picture_path = $path . '/picture-' . $account->uid . '.jpg';
     $file = fopen($picture_path, 'w');
     fwrite($file, $picture_result->data);
@@ -278,8 +437,19 @@ function fboauth_access_token($code, $action_name, $app_id = NULL, $app_secret =
     'redirect_uri' => fboauth_action_url('fboauth/' . $action_name, array('absolute' => TRUE, 'query' => !empty($_GET['destination']) ? array('destination' => $_GET['destination']) : array())),
     'code' => $code,
   );
-  $token_url = url('https://graph.facebook.com/oauth/access_token', array('absolute' => TRUE, 'query' => $query));
-  $authentication_result = drupal_http_request($token_url);
+
+  $token_url = url('https://graph.facebook.com/' . variable_get('fboauth_apiversion', 'v2.3') . '/oauth/access_token', array('absolute' => TRUE, 'query' => $query));
+
+  $attempts = 5;
+  do {
+    $authentication_result = drupal_http_request($token_url);
+    if ($authentication_result->code == 200) {
+      break;
+    }
+    // Facebook access code generation seems to take a lot of time. That's why we have to wait
+    // some seconds before the code can be acquired.
+    sleep(1);
+  } while (--$attempts > 0);
 
   if ($authentication_result->code != 200) {
     $error = !empty($authentication_result->error) ? $authentication_result->error : t('(no error returned)');
@@ -287,14 +457,7 @@ function fboauth_access_token($code, $action_name, $app_id = NULL, $app_secret =
     watchdog('fboauth', 'Facebook OAuth could not acquire an access token from Facebook. We queried the following URL: <code><pre>@url</pre></code>. Facebook\'s servers returned an error @error: <code><pre>@return</pre></code>', array('@url' => $token_url, '@error' => $error, '@return' => $data));
   }
   else {
-    // The result from Facebook comes back in a query-string-like format,
-    // key1=value1&key2=value2. Parse into an array.
-    $authentication_strings = explode('&', $authentication_result->data);
-    $authentication_values = array();
-    foreach ($authentication_strings as $authentication_string) {
-      list($authentication_key, $authentication_value) = explode('=', $authentication_string);
-      $authentication_values[$authentication_key] = $authentication_value;
-    }
+    $authentication_values = drupal_json_decode($authentication_result->data);
   }
 
   return isset($authentication_values['access_token']) ? $authentication_values['access_token'] : NULL;
@@ -316,17 +479,14 @@ function fboauth_user_permissions($access_requested = NULL) {
   $permissions = array();
   $permission_names = array(
     'user_about_me' => t('About yourself description'),
-    'user_activities' => t('Your activities'),
     'user_birthday' => t('Your birthday'),
     'user_education_history' => t('Your education history'),
     'user_events' => t('Events you\'re attending'),
+    'user_friends' => t('Access your friends'),
     'user_groups' => t('Your groups'),
     'user_hometown' => t('Your hometown'),
-    'user_interests' => t('Your interests'),
     'user_likes' => t('Your likes'),
     'user_location' => t('Your location'),
-    'user_notes' => t('Your notes'),
-    'user_online_presence' => t('Your online/offline status'),
     'user_photo_video_tags' => t('Photos and videos you\'ve been tagged in'),
     'user_photos' => t('Photos you\'ve uploaded'),
     'user_relationships' => t('Access to your family and personal relationships and relationship status'),
@@ -340,11 +500,8 @@ function fboauth_user_permissions($access_requested = NULL) {
     'read_friendlists' => t('Access your lists of friends'),
     'read_insights' => t('Access your Facebook insights data'),
     'read_mailbox' => t('Access your Facebook inbox'),
-    'read_requests' => t('Access your friend requests'),
     'read_stream' => t('Access your new feed'),
-    'xmpp_login' => t('Log you into Facebook chat'),
     'ads_management' => t('Manage your ads'),
-    'user_checkins' => t('Access check-in information'),
   );
 
   $properties = fboauth_user_properties();
@@ -474,12 +631,6 @@ function fboauth_user_properties($include_common = FALSE) {
     'link' => array(
       'label' => t('Facebook profile link'),
     ),
-    'username' => array(
-      'label' => t('Username'),
-    ),
-    'third_party_id' => array(
-      'label' => t('3rd-party ID'),
-    ),
     'timezone' => array(
       'label' => t('Timezone'),
     ),
@@ -528,10 +679,6 @@ function fboauth_user_connections() {
       'permission' => 'manage_pages',
       'label' => t('Account pages'),
     ),
-    'activities' => array(
-      'permission' => 'user_activities',
-      'label' => t('Activities'),
-    ),
     'apprequests' => array(
       'label' => t('App requests'),
       // No permission.
@@ -544,10 +691,6 @@ function fboauth_user_connections() {
       'permission' => 'user_likes',
       'label' => t('Books liked'),
     ),
-    'checkins' => array(
-      'permission' => 'user_checkins',
-      'label' => t('Check-ins'),
-    ),
     'events' => array(
       'permission' => 'user_events',
       'label' => t('Events'),
@@ -560,6 +703,10 @@ function fboauth_user_connections() {
       'permission' => 'read_friendlists',
       'label' => t('Lists of friends'),
     ),
+    'friends' => array(
+      'permission' => 'user_friends',
+      'label' => t('Friends'),
+    ),
     'home' => array(
       'permission' => 'read_stream',
       'label' => t('User\'s news feed'),
@@ -568,10 +715,6 @@ function fboauth_user_connections() {
       'permission' => 'read_mailbox',
       'label' => t('Inbox threads'),
     ),
-    'interests' => array(
-      'permission' => 'user_interests',
-      'label' => t('Interests'),
-    ),
     'likes' => array(
       'permission' => 'user_likes',
       'label' => t('Pages liked'),
@@ -588,10 +731,6 @@ function fboauth_user_connections() {
       'permission' => 'user_likes',
       'label' => t('Music liked'),
     ),
-    'notes' => array(
-      'permission' => 'read_stream',
-      'label' => t('Notes'),
-    ),
     'outbox' => array(
       'permission' => 'read_mailbox',
       'label' => t('Outbox'),
@@ -612,6 +751,10 @@ function fboauth_user_connections() {
       'permission' => 'read_stream',
       'label' => t('Tagged in photos, videos, and posts'),
     ),
+    'tagged_places' => array(
+      'permission' => 'user_tagged_places',
+      'label' => t('List of tagged places for this person'),
+    ),
     'television' => array(
       'permission' => 'user_likes',
       'label' => t('Television liked'),
@@ -653,11 +796,11 @@ function fboauth_graph_query($id, $access_token = NULL, $parameters = array(), $
   }
 
   if ($method == 'GET' || $method == 'DELETE') {
-    $graph_url = url('https://graph.facebook.com/' . $id, array('absolute' => TRUE, 'query' => $parameters));
+    $graph_url = url('https://graph.facebook.com/' . variable_get('fboauth_apiversion', 'v2.3') . '/' . $id, array('absolute' => TRUE, 'query' => $parameters));
     $graph_result = drupal_http_request($graph_url, array(), $method);
   }
   elseif ($method == 'POST') {
-    $graph_url = 'https://graph.facebook.com/' . $id;
+    $graph_url = 'https://graph.facebook.com/' . variable_get('fboauth_apiversion', 'v2.3') . '/' . $id;
     $post_data = http_build_query($parameters, '', '&');
     $graph_result = drupal_http_request($graph_url, array(), $method, $post_data);
   }
@@ -666,7 +809,7 @@ function fboauth_graph_query($id, $access_token = NULL, $parameters = array(), $
   }
 
   // If the response contains a redirect (such as to an image), return the
-  // redirect as the data. i.e. https://graph.facebook.com/19292868552/picture.
+  // redirect as the data. i.e. https://graph.facebook.com/v2.3/19292868552/picture.
   if (isset($graph_result->redirect_url)) {
     $data = array(
       'data' => $graph_result->data,
@@ -763,4 +906,4 @@ function fboauth_parse_signed_request($signed_request, $secret) {
  */
 function fboauth_base64_url_decode($input) {
   return base64_decode(strtr($input, '-_', '+/'));
-}
\ No newline at end of file
+}
diff --git a/includes/fboauth.pages.inc b/includes/fboauth.pages.inc
index cec1e8d..8dc3094 100644
--- a/includes/fboauth.pages.inc
+++ b/includes/fboauth.pages.inc
@@ -19,6 +19,13 @@ function fboauth_settings_form(&$form_state) {
     '#description' => t('To use Facebook connect, a Facebook Application must be created. Set up your app in <a href="http://www.facebook.com/developers/apps.php">my apps</a> on Facebook.') . ' ' . t('Enter your App ID here.'),
     '#default_value' => variable_get('fboauth_id', ''),
   );
+  $form['fboauth_apiversion'] = array(
+    '#type' => 'select',
+    '#title' => t('API Version'),
+    '#options' => drupal_map_assoc(array('v2.3', 'v2.4', 'v2.5')),
+    '#description' => t('To use Facebook connect, a Facebook Application must be created. Set up your app in <a href="http://www.facebook.com/developers/apps.php">my apps</a> on Facebook.') . ' ' . t('Enter your App API version here. If your version is prior to 2.3 select v2.3 here.'),
+    '#default_value' => variable_get('fboauth_apiversion', 'v2.3'),
+  );
   $form['fboauth_secret'] = array(
     '#type' => 'textfield',
     '#title' => t('App Secret'),
@@ -27,6 +34,38 @@ function fboauth_settings_form(&$form_state) {
     '#description' => t('To use Facebook connect, a Facebook Application must be created. Set up your app in <a href="http://www.facebook.com/developers/apps.php">my apps</a> on Facebook.') . ' ' . t('Enter your App Secret here.'),
     '#default_value' => variable_get('fboauth_secret', ''),
   );
+  $form['fboauth_debug'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Capture Debug Information'),
+    '#default_value' => variable_get('fboauth_debug', ''),
+    '#description' => t('When checked, if Database Logging is enabled, it will store the raw user object returned by Facebook. You can see it under <em>admin/reports/dblog</em>. Uncheck for production sites.'),
+  );
+
+  $form['fboauth_popup'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use a popup window for Facebook authentication dialog'),
+    '#description' => t('This may provide a better user experience when logging into Facebook, but may also be blocked by browser popup blocker plugins.'),
+    '#default_value' => variable_get('fboauth_popup', 1),
+  );
+
+  $form['fboauth_always_load_js'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Always load the popup window javascript file'),
+    '#description' => t('This will load the popup window javascript file on every page load rather than only when the block is loaded. This is mainly for when you want to implement the Facebook button code manually.'),
+    '#default_value' => variable_get('fboauth_always_load_js', 0),
+    '#states' => array(
+      'invisible' => array(
+        ':input[name="fboauth_popup"]' => array('checked' => FALSE),
+      ),
+    ),
+  );
+
+  $form['fboauth_anon_connect'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Allow anonymous users to connect an existing unconnected drupal account to their Facebook account?'),
+    '#description' => t('Should anonymous users be able to connect an existing unconnected drupal account to a Facebook account based solely on an email address match?'),
+    '#default_value' => variable_get('fboauth_anon_connect', TRUE),
+  );
 
   $form['fboauth_basic_mapping'] = array(
     '#type' => 'fieldset',
@@ -53,8 +92,8 @@ function fboauth_settings_form(&$form_state) {
     '#type' => 'radios',
     '#title' => t('User name import'),
     '#options' => array(
-      'username' => t('Facebook username (i.e. johnsmith)'),
       'name' => t('Real name (i.e. John Smith)'),
+      'id' => t('Profile ID (i.e. 10152608721639101)'),
     ),
     '#description' => t('Select the Facebook value used to set the user\'s name when connecting with Facebook.'),
     '#default_value' => variable_get('fboauth_user_username', 'username'),
@@ -88,7 +127,7 @@ function fboauth_settings_form(&$form_state) {
     '#type' => 'checkboxes',
     '#options' => $property_options,
     '#default_value' => variable_get('fboauth_user_properties', array()),
-    '#description' => t('The following properties are always available: id, name, first_name, last_name, gender, locale, link, username, third_party_id, timezone, updated_time, and verified.'),
+    '#description' => t('The following properties are always available: id, name, first_name, last_name, gender, locale, link, timezone, updated_time, and verified.'),
   );
 
   $connections = fboauth_user_connections();
@@ -121,6 +160,15 @@ function fboauth_settings_form_validate($form, &$form_state) {
   // Remove trailing spaces from keys.
   $form_state['values']['fboauth_id'] = trim($form_state['values']['fboauth_id']);
   $form_state['values']['fboauth_secret'] = trim($form_state['values']['fboauth_secret']);
+  variable_set('fboauth_popup', $form_state['values']['fboauth_popup']);
+
+  // Set fboauth_always_load_js to be FALSE if fboauth_always_load_js has been
+  // turned off as well.
+  $load_js = $form_state['values']['fboauth_always_load_js'];
+  if (!$form_state['values']['fboauth_popup']) {
+    $load_js = 0;
+  }
+  variable_set('fboauth_always_load_js', $load_js);
 
   // Do some basic data input validation.
   if (!is_numeric($form_state['values']['fboauth_id']) || strlen($form_state['values']['fboauth_id']) > 20) {
@@ -136,7 +184,11 @@ function fboauth_settings_form_validate($form, &$form_state) {
  */
 function fboauth_settings_form_submit($form, &$form_state) {
   variable_set('fboauth_id', $form_state['values']['fboauth_id']);
+  variable_set('fboauth_apiversion', $form_state['values']['fboauth_apiversion']);
   variable_set('fboauth_secret', $form_state['values']['fboauth_secret']);
+  variable_set('fboauth_debug', $form_state['values']['fboauth_debug']);
+
+  variable_set('fboauth_anon_connect', $form_state['values']['fboauth_anon_connect']);
 
   variable_set('fboauth_user_email', $form_state['values']['fboauth_user_email']);
   variable_set('fboauth_user_username', $form_state['values']['fboauth_user_username']);
-- 
1.9.5.msysgit.0

