Changeset 1252

Show
Ignore:
Timestamp:
10/17/10 18:31:00 (3 years ago)
Author:
d0nut
Message:

facebook 2.0.0 RC 2

  • bypass password queries, since facebook users do have have passwords
  • add facebook login to existing wcf user
Location:
facebook
Files:
1 added
2 removed
5 modified
2 copied

Legend:

Unmodified
Added
Removed
  • facebook/de-informal.xml

    r1208 r1252  
    11<?xml version="1.0" encoding="UTF-8"?> 
    22<!DOCTYPE language SYSTEM "http://www.woltlab.com/DTDs/language.dtd"> 
    3 <language languagecode="de"> 
     3<language languagecode="de-informal"> 
    44        <category name="wcf.acp.option"> 
    55                <item name="wcf.acp.option.module_facebook"><![CDATA[Facebook]]></item> 
     
    1212                <item name="wcf.acp.option.facebook_secret.description"><![CDATA[Geben Sie hier den Anwendungs-Geheimcode ein, den Sie auf <a href="http://wiki.developers.facebook.com/index.php/Connect/Setting_Up_Your_Site">Facebook</a> erhalten haben.]]></item> 
    1313        </category> 
     14        <category name="wcf.facebook"> 
     15                <item name="wcf.facebook.title"><![CDATA[Facebook]]></item> 
     16                <item name="wcf.facebook.status.connected"><![CDATA[Sie sind erfolgreich mit Facebook verbunden.]]></item> 
     17                <item name="wcf.facebook.status.alreadyAssigned"><![CDATA[Der Benutzer &laquo;{$username}&raquo; benutzt ihren Facebook Login bereits.]]></item> 
     18        </category> 
    1419</language> 
  • facebook/de.xml

    r1208 r1252  
    1212                <item name="wcf.acp.option.facebook_secret.description"><![CDATA[Geben Sie hier den Anwendungs-Geheimcode ein, den Sie auf <a href="http://wiki.developers.facebook.com/index.php/Connect/Setting_Up_Your_Site">Facebook</a> erhalten haben.]]></item> 
    1313        </category> 
     14        <category name="wcf.facebook"> 
     15                <item name="wcf.facebook.title"><![CDATA[Facebook]]></item> 
     16                <item name="wcf.facebook.status.connected"><![CDATA[Sie sind erfolgreich mit Facebook verbunden.]]></item> 
     17                <item name="wcf.facebook.status.alreadyAssigned"><![CDATA[Der Benutzer &laquo;{$username}&raquo; benutzt ihren Facebook Login bereits.]]></item> 
     18        </category> 
    1419</language> 
  • facebook/en.xml

    r1208 r1252  
    1212                <item name="wcf.acp.option.facebook_secret.description"><![CDATA[Enter your SecretKey.]]></item> 
    1313        </category> 
     14        <category name="wcf.facebook"> 
     15                <item name="wcf.facebook.title"><![CDATA[Facebook]]></item> 
     16                <item name="wcf.facebook.status.connected"><![CDATA[Your are successfully connected to facebook.]]></item> 
     17                <item name="wcf.facebook.status.alreadyAssigned"><![CDATA[Your facebook login was already linked with the user &laquo;{$username}&raquo;.]]></item> 
     18        </category> 
    1419</language> 
  • facebook/eventlistener.xml

    r1208 r1252  
    66                        <eventclassname>UserLoginForm</eventclassname> 
    77                        <eventname>readData</eventname> 
     8                        <listenerclassfile>lib/system/event/listener/UserLoginFacebookListener.class.php</listenerclassfile> 
     9                </eventlistener> 
     10                <eventlistener> 
     11                        <eventclassname>AccountManagementForm</eventclassname> 
     12                        <eventname>validate</eventname> 
     13                        <listenerclassfile>lib/system/event/listener/UserLoginFacebookListener.class.php</listenerclassfile> 
     14                </eventlistener> 
     15                <eventlistener> 
     16                        <eventclassname>UserProfileEditForm</eventclassname> 
     17                        <eventname>assignVariables</eventname> 
    818                        <listenerclassfile>lib/system/event/listener/UserLoginFacebookListener.class.php</listenerclassfile> 
    919                </eventlistener> 
  • facebook/files/lib/system/event/listener/UserLoginFacebookListener.class.php

    r1218 r1252  
    11<?php 
    2 require_once(WCF_DIR.'lib/system/event/EventListener.class.php'); 
    3 require_once(WCF_DIR.'lib/data/facebook/Facebook.class.php'); 
    4 require_once(WCF_DIR.'lib/data/user/avatar/AvatarEditor.class.php'); 
    5 require_once(WCF_DIR.'lib/data/user/UserEditor.class.php'); 
     2require_once(WCF_DIR.'lib/util/FacebookUtil.class.php'); 
    63 
    74/** 
    85 * login will display facebook login button and manage all the login stuff 
    96 *  
    10  * @author      Tim Wittenberg, Torben Brodt 
     7 * @author      Torben Brodt 
    118 * @url         http://trac.easy-coding.de/trac/wcf/wiki/facebook 
    129 * @license     GNU General Public License <http://opensource.org/licenses/gpl-3.0.html> 
    1310 */ 
    1411class UserLoginFacebookListener implements EventListener { 
    15         /** 
    16          * from eventlistener 
    17          * 
    18          * @var UserLoginForm 
    19          */ 
    20         protected $eventObj; 
    21          
    22         /** 
    23          * from eventlistener 
    24          * 
    25          * @var string 
    26          */ 
    27         protected $className; 
    28  
    29         /** 
    30          * facebook api object 
    31          * 
    32          * @var Facebok 
    33          */ 
    34         public $facebook; 
    3512 
    3613        /** 
     
    4118                        return; 
    4219                } 
     20                 
     21                switch($className) { 
     22                        // login or register with facebook 
     23                        case 'UserLoginForm': 
     24                                // readData 
     25                                FacebookUtil::loginOrRegister($eventObj); 
     26                        break; 
     27                         
     28                        // registered user links with facebook 
     29                        case 'UserProfileEditForm': 
     30                                // assignVariables 
     31                                if($eventObj->activeCategory == 'settings.general') { 
     32                                        FacebookUtil::updateCurrentUser(); 
     33                                } 
     34                        break; 
     35                         
     36                        // password validations can be skipped if facebook auth is successfully 
     37                        case 'AccountManagementForm': 
     38                                // validate 
     39                                if(FacebookUtil::isValidFacebookUser()) { 
    4340 
    44                 $this->eventObj = $eventObj; 
    45                 $this->className = $className; 
    46  
    47                 if(method_exists($this, $eventName)) { 
    48                         $this->$eventName(); 
    49                 } 
    50         } 
    51  
    52         /** 
    53          * is there an existing user with given facebook id? 
    54          * 
    55          * @param       array           $me 
    56          * @return      User 
    57          */ 
    58         protected function getFacebookEnabledUser($me) { 
    59                 $sql = "SELECT          utb.userID 
    60                         FROM            wcf".WCF_N."_user_to_facebook utb 
    61                         WHERE           utb.facebookID = ".intval($me['id']); 
    62                 $row = WCF::getDB()->getFirstRow($sql); 
    63  
    64                 $user = $row ? new User($row['userID']) : null; 
    65                 return $user && $user->userID ? $user : null; 
    66         } 
    67  
    68         /** 
    69          * adds facebook link to user 
    70          * 
    71          * @param       integer         $facebookID 
    72          * @param       User            $user 
    73          * @return      boolean 
    74          */ 
    75         protected function addFacebookUser($facebookID, $user) { 
    76                 $sql = "REPLACE INTO    wcf".WCF_N."_user_to_facebook 
    77                                         (facebookID, userID) 
    78                         VALUES          (".intval($facebookID).", ".intval($user->userID).")"; 
    79  
    80                 return WCF::getDB()->sendQuery($sql); 
    81         } 
    82  
    83         /** 
    84          * is there an existing user matching the given email address from facebook? 
    85          * 
    86          * @param       array           $me 
    87          * @return      User 
    88          */ 
    89         protected function getEmailUser($me) { 
    90                 $user = new User(null, null, null, $me['email']); 
    91                 return $user->userID ? $user : null; 
    92         } 
    93  
    94         /** 
    95          * @see UserLoginForm::readData 
    96          */ 
    97         public function readData() { 
    98  
    99                 // Create our Application instance. 
    100                 $this->facebook = new Facebook(array( 
    101                         'appId'  => FACEBOOK_APPID, 
    102                         'secret' => FACEBOOK_SECRET, 
    103                         'cookie' => true, 
    104                 )); 
    105  
    106                 // We may or may not have this data based on a $_GET or $_COOKIE based session. 
    107                 // 
    108                 // If we get a session here, it means we found a correctly signed session using 
    109                 // the Application Secret only Facebook and the Application know. We dont know 
    110                 // if it is still valid until we make an API call using the session. A session 
    111                 // can become invalid if it has already expired (should not be getting the 
    112                 // session back in this case) or if the user logged out of Facebook. 
    113                 $session = $this->facebook->getSession(); 
    114  
    115                 $me = null; 
    116                 $uid = array(); 
    117  
    118                 // Session based API call. 
    119                 if ($session) { 
    120                         try { 
    121                                 $uid = $this->facebook->getUser(); 
    122                                 $me = $this->facebook->api('/me'); 
    123                         } catch (FacebookApiException $e) { 
    124                                 error_log($e); 
    125                         } 
    126                 } 
    127  
    128                 // no permissions granted, ask for login 
    129                 if(!$me) { 
    130                         $loginUrl = $this->facebook->getLoginUrl(array( 
    131                                 'req_perms' => 'email', 
    132                                 'display' => 'popup' 
    133                         )); 
    134  
    135                         WCF::getTPL()->assign(array( 
    136                                 'session' => $session, 
    137                                 'loginUrl' => $loginUrl, 
    138                         )); 
    139  
    140                         WCF::getTPL()->append('additionalFields', WCF::getTPL()->fetch('facebookLogin')); 
    141                         return; 
    142                 } 
    143  
    144                 // facebook permissions granted, does an login exist? 
    145                 $user = $this->getFacebookEnabledUser($me); 
    146  
    147                 // facebook permissions granted but no login exists 
    148                 if(!$user) { 
    149  
    150                         // facebook is ultimativly trusted, if you get an account there, 
    151                         // you can get the account with the same email here! 
    152                         $user = $this->getEmailUser($me); 
    153  
    154                         // totally unknown, add a new user 
    155                         if(!$user) { 
    156                                 $user = $this->registerUser($me); 
    157                         } 
    158  
    159                         // update avatar 
    160                         $this->updateAvatar('https://graph.facebook.com/'.$me['id'].'/picture', $user); 
    161  
    162                         // either user is new, oder just got a link, but add a facebook link 
    163                         $this->addFacebookUser($me['id'], $user); 
    164                 } 
    165  
    166                 if($user) { 
    167  
    168                         // UserLoginForm should not write cookie, since interfaces only support unhashed password 
    169                         $this->eventObj->useCookies = 0; 
    170  
    171                         // set cookies 
    172                         UserAuth::getInstance()->storeAccessData($user, $user->username, $user->password); 
    173                         HeaderUtil::setCookie('password', $user->password, TIME_NOW + 365 * 24 * 3600); 
    174  
    175                         // save cookie and redirect 
    176                         $this->eventObj->user = $user; 
    177                         $this->eventObj->save(); 
    178  
    179                         exit; 
    180                 } 
    181         } 
    182  
    183         /** 
    184          * get a available username 
    185          * 
    186          * @param       string          $username 
    187          * @return      string 
    188          */ 
    189         protected function findUsername($username) { 
    190                 if(!UserUtil::isValidUsername($username)) { 
    191                         return null; 
    192                 } 
    193  
    194                 if(UserUtil::isAvailableUsername($username)) { 
    195                         return $username; 
    196                 } 
    197  
    198                 // try to increase last digit 
    199                 if(preg_match('/(\d+)$/', $username, $res)) { 
    200                         return $this->findUsername(preg_replace('/(\d+)/', ($res[1] + 1), $username)); 
    201                 } else { 
    202                         return $this->findUsername($username.'2'); 
    203                 } 
    204         } 
    205  
    206         /** 
    207          * registers a new user with valid username 
    208          * 
    209          * @param       array           $me 
    210          * @return      User 
    211          */ 
    212         protected function registerUser($me) { 
    213                 $user = null; 
    214                 // get a valid username 
    215                 $username = $this->findUsername($me['name']); 
    216  
    217                 // create new user 
    218                 if($username) { 
    219                         $user = $this->createNewUser( 
    220                                 $username, 
    221                                 $me['email'], 
    222                                 $me['link'] 
    223                         ); 
    224                 } else { 
    225                         throw new SystemException('invalid facebook username: '.$me['name']); 
    226                 } 
    227                 return $user; 
    228         } 
    229  
    230         /** 
    231          * adds a new wcf user and sends, bypasses all registration steps and send out mails 
    232          * 
    233          * @param       string          $username 
    234          * @param       string          $email 
    235          * @param       string          $facebookLink 
    236          * @return      User 
    237          */ 
    238         protected function createNewUser($username, $email, $facebookLink) { 
    239  
    240                 $password = UserRegistrationUtil::getNewPassword((REGISTER_PASSWORD_MIN_LENGTH > 9 ? REGISTER_PASSWORD_MIN_LENGTH : 9)); 
    241                 $groups = array(); 
    242                 $activeOptions = array(); 
    243  
    244                 $additionalFields = array(); 
    245                 $additionalFields['languageID'] = WCF::getLanguage()->getLanguageID(); 
    246                 $additionalFields['registrationIpAddress'] = WCF::getSession()->ipAddress; 
    247  
    248                 $visibleLanguages = $this->getAvailableLanguages(); 
    249                 $visibleLanguages = array_keys($visibleLanguages); 
    250                 $addDefaultGroups = true; 
    251  
    252                 // create the user 
    253                 if(($user = UserEditor::create($username, $email, $password, $groups, $activeOptions, $additionalFields, $visibleLanguages, $addDefaultGroups))) { 
    254  
    255                         // notify admin 
    256                         if (REGISTER_ADMIN_NOTIFICATION) { 
    257                                 // get default language 
    258                                 $language = (WCF::getLanguage()->getLanguageID() != Language::getDefaultLanguageID() 
    259                                         ? new Language(Language::getDefaultLanguageID()) 
    260                                         : WCF::getLanguage()); 
    261                                 $language->setLocale(); 
    262  
    263                                 // send mail 
    264                                 require_once(WCF_DIR.'lib/data/mail/Mail.class.php'); 
    265                                 $mail = new Mail( 
    266                                         MAIL_ADMIN_ADDRESS, 
    267                                         $language->get('wcf.user.register.notification.mail.subject', array( 
    268                                                 'PAGE_TITLE' => $language->get(PAGE_TITLE) 
    269                                         )), 
    270                                         $language->get('wcf.user.register.notification.mail', array( 
    271                                                 'PAGE_TITLE' => $language->get(PAGE_TITLE), 
    272                                                 '$username' => $user->username 
    273                                         )) 
    274                                 ); 
    275                                 $mail->send(); 
    276  
    277                                 WCF::getLanguage()->setLocale(); 
    278                         } 
    279                 } 
    280  
    281                 return $user; 
    282         } 
    283  
    284         /** 
    285          * Returns a list of all available languages. 
    286          * 
    287          * @return      array 
    288          */ 
    289         protected function getAvailableLanguages() { 
    290                 $availableLanguages = array(); 
    291                 foreach (Language::getAvailableLanguages(PACKAGE_ID) as $language) { 
    292                         $availableLanguages[$language['languageID']] = WCF::getLanguage()->get('wcf.global.language.'.$language['languageCode']); 
    293                 } 
    294  
    295                 // sort languages 
    296                 StringUtil::sort($availableLanguages); 
    297  
    298                 return $availableLanguages; 
    299         } 
    300  
    301         /** 
    302          * downloads facebook image and saves as avatar 
    303          * 
    304          * @param       string          $avatarURL 
    305          * @param       User            $user 
    306          * @return      boolean 
    307          */ 
    308         protected function updateAvatar($avatarURL, $user) { 
    309                 // existing avatar? skip facebook download 
    310                 if ($user->avatarID || empty($avatarURL)) { 
    311                         return false; 
    312                 } 
    313  
    314                 try { 
    315                         $avatarID = 0; 
    316                         $tmpName = FileUtil::downloadFileFromHttp($avatarURL, 'avatar'); 
    317                         $avatarID = AvatarEditor::create($tmpName, $avatarURL, 'avatarURL', $user->userID); 
    318                 } 
    319                 catch (Exception $e) { 
    320  
    321                         // skip, download is not that important 
    322                         return false; 
    323                 } 
    324  
    325                 if($avatarID) { 
    326  
    327                         // update user 
    328                         $sql = "UPDATE  wcf".WCF_N."_user 
    329                                 SET     avatarID = ".$avatarID." 
    330                                 WHERE   userID = ".$user->userID; 
    331                         return WCF::getDB()->sendQuery($sql); 
     41                                        // bypass password query with a little hack 
     42                                        $password = UserRegistrationUtil::getNewPassword((REGISTER_PASSWORD_MIN_LENGTH > 9 ? REGISTER_PASSWORD_MIN_LENGTH : 9)); 
     43                                        WCF::getUser()->password = StringUtil::getDoubleSaltedHash($password, WCF::getUser()->salt); 
     44                                        $eventObj->password = $password; 
     45                                } 
     46                        break; 
    33247                } 
    33348        } 
  • facebook/files/lib/util/FacebookUtil.class.php

    r1218 r1252  
    44require_once(WCF_DIR.'lib/data/user/avatar/AvatarEditor.class.php'); 
    55require_once(WCF_DIR.'lib/data/user/UserEditor.class.php'); 
     6require_once(WCF_DIR.'lib/util/UserRegistrationUtil.class.php'); 
    67 
    78/** 
    89 * login will display facebook login button and manage all the login stuff 
    910 *  
    10  * @author      Tim Wittenberg, Torben Brodt 
     11 * @author      Torben Brodt 
    1112 * @url         http://trac.easy-coding.de/trac/wcf/wiki/facebook 
    1213 * @license     GNU General Public License <http://opensource.org/licenses/gpl-3.0.html> 
    1314 */ 
    14 class UserLoginFacebookListener implements EventListener { 
    15         /** 
    16          * from eventlistener 
    17          * 
    18          * @var UserLoginForm 
    19          */ 
    20         protected $eventObj; 
    21          
    22         /** 
    23          * from eventlistener 
    24          * 
    25          * @var string 
    26          */ 
    27         protected $className; 
     15class FacebookUtil { 
    2816 
    2917        /** 
     
    3220         * @var Facebok 
    3321         */ 
    34         public $facebook; 
    35  
    36         /** 
    37          * @see EventListener::execute() 
    38          */ 
    39         public function execute($eventObj, $className, $eventName) { 
    40                 if (!MODULE_FACEBOOK || !FACEBOOK_APPID || !FACEBOOK_SECRET) { 
    41                         return; 
    42                 } 
    43  
    44                 $this->eventObj = $eventObj; 
    45                 $this->className = $className; 
    46  
    47                 if(method_exists($this, $eventName)) { 
    48                         $this->$eventName(); 
    49                 } 
    50         } 
     22        public static $facebook; 
    5123 
    5224        /** 
     
    5628         * @return      User 
    5729         */ 
    58         protected function getFacebookEnabledUser($me) { 
     30        protected static function getFacebookEnabledUser($me) { 
    5931                $sql = "SELECT          utb.userID 
    6032                        FROM            wcf".WCF_N."_user_to_facebook utb 
     
    6739 
    6840        /** 
     41         * is there an existing user with given facebook id? 
     42         * 
     43         * @param       integer         $userID 
     44         * @return      boolean 
     45         */ 
     46        protected static function hasFacebookAccount($userID) { 
     47                $sql = "SELECT          utb.facebookID 
     48                        FROM            wcf".WCF_N."_user_to_facebook utb 
     49                        WHERE           utb.userID = ".intval($userID); 
     50                $row = WCF::getDB()->getFirstRow($sql); 
     51 
     52                return $row && $row['facebookID'] > 0; 
     53        } 
     54 
     55        /** 
    6956         * adds facebook link to user 
    7057         * 
     
    7360         * @return      boolean 
    7461         */ 
    75         protected function addFacebookUser($facebookID, $user) { 
     62        protected static function addFacebookUser($facebookID, $user) { 
    7663                $sql = "REPLACE INTO    wcf".WCF_N."_user_to_facebook 
    7764                                        (facebookID, userID) 
     
    8774         * @return      User 
    8875         */ 
    89         protected function getEmailUser($me) { 
     76        protected static function getEmailUser($me) { 
    9077                $user = new User(null, null, null, $me['email']); 
    9178                return $user->userID ? $user : null; 
    9279        } 
    93  
    94         /** 
    95          * @see UserLoginForm::readData 
    96          */ 
    97         public function readData() { 
    98  
     80         
     81        protected static function getSesssion() { 
    9982                // Create our Application instance. 
    100                 $this->facebook = new Facebook(array( 
     83                self::$facebook = new Facebook(array( 
    10184                        'appId'  => FACEBOOK_APPID, 
    10285                        'secret' => FACEBOOK_SECRET, 
     
    11194                // can become invalid if it has already expired (should not be getting the 
    11295                // session back in this case) or if the user logged out of Facebook. 
    113                 $session = $this->facebook->getSession(); 
     96                $session = self::$facebook->getSession(); 
     97                 
     98                return $session; 
     99        } 
     100 
     101        /** 
     102         * 
     103         */ 
     104        public static function isValidFacebookUser() { 
     105         
     106                // did connect? 
     107                if(!self::hasFacebookAccount(WCF::getUser()->userID)) { 
     108                        return false; 
     109                } 
     110 
     111                // We may or may not have this data based on a $_GET or $_COOKIE based session. 
     112                $session = self::getSession(); 
    114113 
    115114                $me = null; 
     
    119118                if ($session) { 
    120119                        try { 
    121                                 $uid = $this->facebook->getUser(); 
    122                                 $me = $this->facebook->api('/me'); 
     120                                $uid = self::$facebook->getUser(); 
     121                                $me = self::$facebook->api('/me'); 
    123122                        } catch (FacebookApiException $e) { 
    124123                                error_log($e); 
     
    128127                // no permissions granted, ask for login 
    129128                if(!$me) { 
    130                         $loginUrl = $this->facebook->getLoginUrl(array( 
     129                        $loginUrl = self::$facebook->getLoginUrl(array( 
    131130                                'req_perms' => 'email', 
    132131                                'display' => 'popup' 
     
    139138 
    140139                        WCF::getTPL()->append('additionalFields', WCF::getTPL()->fetch('facebookLogin')); 
     140                        return false; 
     141                } 
     142 
     143                // facebook permissions granted, does an login exist? 
     144                $user = self::getFacebookEnabledUser($me); 
     145 
     146                // facebook permissions granted and login is linked with current user 
     147                return $user && $user->userID == WCF::getUser()->userID; 
     148        } 
     149 
     150        /** 
     151         * @see UserLoginForm::readData 
     152         */ 
     153        public static function updateCurrentUser() { 
     154 
     155                // We may or may not have this data based on a $_GET or $_COOKIE based session. 
     156                $session = self::getSession(); 
     157 
     158                $me = null; 
     159                $uid = array(); 
     160 
     161                // Session based API call. 
     162                if ($session) { 
     163                        try { 
     164                                $uid = self::$facebook->getUser(); 
     165                                $me = self::$facebook->api('/me'); 
     166                        } catch (FacebookApiException $e) { 
     167                                error_log($e); 
     168                        } 
     169                } 
     170 
     171                // no permissions granted, ask for login 
     172                if(!$me) { 
     173                        $loginUrl = self::$facebook->getLoginUrl(array( 
     174                                'req_perms' => 'email', 
     175                                'display' => 'popup' 
     176                        )); 
     177 
     178                        WCF::getTPL()->assign(array( 
     179                                'session' => $session, 
     180                                'loginUrl' => $loginUrl, 
     181                        )); 
     182 
     183                        WCF::getTPL()->append('additionalFields', '<fieldset> 
     184                                <legend>'.WCF::getLanguage()->get('wcf.facebook.title').'</legend> 
     185                                '.WCF::getTPL()->fetch('facebookLogin').' 
     186                        </fieldset>'); 
    141187                        return; 
    142188                } 
    143189 
    144190                // facebook permissions granted, does an login exist? 
    145                 $user = $this->getFacebookEnabledUser($me); 
     191                $user = self::getFacebookEnabledUser($me); 
     192 
     193                // facebook login not used yet, facebook permissions granted, update account info 
     194                if(!$user) { 
     195 
     196                        // update avatar (only if avatar is not given) 
     197                        self::updateAvatar('https://graph.facebook.com/'.$me['id'].'/picture', $user); 
     198 
     199                        // either user is new, oder just got a link, but add a facebook link 
     200                        self::addFacebookUser($me['id'], $user); 
     201 
     202                        return true; 
     203                } 
     204 
     205                // user already exists, and login is linked to the current account 
     206                else if($user && $user->userID == WCF::getUser()) { 
     207                        WCF::getTPL()->append('additionalFields', '<fieldset> 
     208                                <legend>'.WCF::getLanguage()->get('wcf.facebook.title').'</legend> 
     209                                '.WCF::getLanguage()->get('wcf.facebook.status.connected').' 
     210                        </fieldset>'); 
     211                } 
     212 
     213                // user already exists, but the login is linked to another account 
     214                else { 
     215                        WCF::getTPL()->append('additionalFields', '<fieldset> 
     216                                <legend>'.WCF::getLanguage()->get('wcf.facebook.title').'</legend> 
     217                                '.WCF::getLanguage()->getDynamicVariable('wcf.facebook.status.alreadyAssigned', array( 
     218                                        'username' => $user->username 
     219                                )).' 
     220                        </fieldset>'); 
     221                } 
     222        } 
     223 
     224        /** 
     225         * @see UserLoginForm::readData 
     226         */ 
     227        public static function loginOrRegister($eventObj) { 
     228 
     229                $session = self::getSession(); 
     230 
     231                $me = null; 
     232                $uid = array(); 
     233 
     234                // Session based API call. 
     235                if ($session) { 
     236                        try { 
     237                                $uid = self::$facebook->getUser(); 
     238                                $me = self::$facebook->api('/me'); 
     239                        } catch (FacebookApiException $e) { 
     240                                error_log($e); 
     241                        } 
     242                } 
     243 
     244                // no permissions granted, ask for login 
     245                if(!$me) { 
     246                        $loginUrl = self::$facebook->getLoginUrl(array( 
     247                                'req_perms' => 'email', 
     248                                'display' => 'popup' 
     249                        )); 
     250 
     251                        WCF::getTPL()->assign(array( 
     252                                'session' => $session, 
     253                                'loginUrl' => $loginUrl, 
     254                        )); 
     255 
     256                        WCF::getTPL()->append('additionalFields', WCF::getTPL()->fetch('facebookLogin')); 
     257                        return; 
     258                } 
     259 
     260                // facebook permissions granted, does an login exist? 
     261                $user = self::getFacebookEnabledUser($me); 
    146262 
    147263                // facebook permissions granted but no login exists 
     
    150266                        // facebook is ultimativly trusted, if you get an account there, 
    151267                        // you can get the account with the same email here! 
    152                         $user = $this->getEmailUser($me); 
     268                        $user = self::getEmailUser($me); 
    153269 
    154270                        // totally unknown, add a new user 
    155271                        if(!$user) { 
    156                                 $user = $this->registerUser($me); 
     272                                $user = self::registerUser($me); 
    157273                        } 
    158274 
    159275                        // update avatar 
    160                         $this->updateAvatar('https://graph.facebook.com/'.$me['id'].'/picture', $user); 
     276                        self::updateAvatar('https://graph.facebook.com/'.$me['id'].'/picture', $user); 
    161277 
    162278                        // either user is new, oder just got a link, but add a facebook link 
    163                         $this->addFacebookUser($me['id'], $user); 
     279                        self::addFacebookUser($me['id'], $user); 
    164280                } 
    165281 
     
    167283 
    168284                        // UserLoginForm should not write cookie, since interfaces only support unhashed password 
    169                         $this->eventObj->useCookies = 0; 
     285                        $eventObj->useCookies = 0; 
    170286 
    171287                        // set cookies 
     
    174290 
    175291                        // save cookie and redirect 
    176                         $this->eventObj->user = $user; 
    177                         $this->eventObj->save(); 
     292                        $eventObj->user = $user; 
     293                        $eventObj->save(); 
    178294 
    179295                        exit; 
     
    187303         * @return      string 
    188304         */ 
    189         protected function findUsername($username) { 
     305        protected static function findUsername($username) { 
    190306                if(!UserUtil::isValidUsername($username)) { 
    191307                        return null; 
     
    198314                // try to increase last digit 
    199315                if(preg_match('/(\d+)$/', $username, $res)) { 
    200                         return $this->findUsername(preg_replace('/(\d+)/', ($res[1] + 1), $username)); 
     316                        return self::findUsername(preg_replace('/(\d+)/', ($res[1] + 1), $username)); 
    201317                } else { 
    202                         return $this->findUsername($username.'2'); 
     318                        return self::findUsername($username.'2'); 
    203319                } 
    204320        } 
     
    210326         * @return      User 
    211327         */ 
    212         protected function registerUser($me) { 
     328        protected static function registerUser($me) { 
    213329                $user = null; 
    214330                // get a valid username 
    215                 $username = $this->findUsername($me['name']); 
     331                $username = self::findUsername($me['name']); 
    216332 
    217333                // create new user 
    218334                if($username) { 
    219                         $user = $this->createNewUser( 
     335                        $user = self::createNewUser( 
    220336                                $username, 
    221337                                $me['email'], 
     
    236352         * @return      User 
    237353         */ 
    238         protected function createNewUser($username, $email, $facebookLink) { 
     354        protected static function createNewUser($username, $email, $facebookLink) { 
    239355 
    240356                $password = UserRegistrationUtil::getNewPassword((REGISTER_PASSWORD_MIN_LENGTH > 9 ? REGISTER_PASSWORD_MIN_LENGTH : 9)); 
     
    246362                $additionalFields['registrationIpAddress'] = WCF::getSession()->ipAddress; 
    247363 
    248                 $visibleLanguages = $this->getAvailableLanguages(); 
     364                $visibleLanguages = self::getAvailableLanguages(); 
    249365                $visibleLanguages = array_keys($visibleLanguages); 
    250366                $addDefaultGroups = true; 
     
    287403         * @return      array 
    288404         */ 
    289         protected function getAvailableLanguages() { 
     405        protected static function getAvailableLanguages() { 
    290406                $availableLanguages = array(); 
    291407                foreach (Language::getAvailableLanguages(PACKAGE_ID) as $language) { 
     
    306422         * @return      boolean 
    307423         */ 
    308         protected function updateAvatar($avatarURL, $user) { 
     424        protected static function updateAvatar($avatarURL, $user) { 
    309425                // existing avatar? skip facebook download 
    310426                if ($user->avatarID || empty($avatarURL)) { 
  • facebook/package.xml

    r1208 r1252  
    66                <packagedescription language="de"><![CDATA[Dieses Plugin verbindet Facebook mit dem WCF. So ist z.B. ein Direktlogin via Facebook möglich.]]></packagedescription> 
    77                <packagedescription><![CDATA[This enables all users to login with their facebook account.]]></packagedescription> 
    8                 <version>2.0.0 RC 1</version> 
     8                <version>2.0.0 RC 2</version> 
    99                <date>DATE</date> 
    1010                <plugin>com.woltlab.wcf</plugin> 
     
    2121        </requiredpackages> 
    2222<!-- 
    23         <optionalpackages>               
    24                 <optionalpackage file="optionals/org.gnex.facebook.auth.wbb.tar.gz">org.gnex.facebook.auth.wbb</optionalpackage> 
     23        <optionalpackages> 
    2524                <optionalpackage file="optionals/org.gnex.facebook.auth.profile.tar.gz">org.gnex.facebook.auth.profile</optionalpackage> 
    2625        </optionalpackages> 
     
    3433                <eventlistener>eventlistener.xml</eventlistener> 
    3534                <languages languagecode="de">de.xml</languages> 
     35                <languages languagecode="de-informal">de-informal.xml</languages> 
    3636                <languages languagecode="en">en.xml</languages> 
    3737        </instructions> 
     38 
     39        <instructions type="update" fromversion="2.0.0 RC 1"> 
     40                <files>files.tar</files> 
     41                <eventlistener>eventlistener.xml</eventlistener> 
     42                <languages languagecode="de">de.xml</languages> 
     43                <languages languagecode="de-informal">de-informal.xml</languages> 
     44                <languages languagecode="en">en.xml</languages> 
     45        </instructions> 
     46 
    3847        <instructions type="update" fromversion="1.1.3"> 
    3948                <files>files.tar</files> 
     
    4554                <eventlistener>eventlistener.xml</eventlistener> 
    4655                <languages languagecode="de">de.xml</languages> 
     56                <languages languagecode="de-informal">de-informal.xml</languages> 
    4757                <languages languagecode="en">en.xml</languages> 
    4858                <usercpmenu>usercpmenu.xml</usercpmenu>