]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/FBConnect/FBConnectAuth.php
Reorganized some stuff and made new Facebook Login tab
[quix0rs-gnu-social.git] / plugins / FBConnect / FBConnectAuth.php
1 <?php
2 /**
3  * Laconica, the distributed open-source microblogging tool
4  *
5  * Plugin to enable Facebook Connect
6  *
7  * PHP version 5
8  *
9  * LICENCE: This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU Affero General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Affero General Public License for more details.
18  *
19  * You should have received a copy of the GNU Affero General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  * @category  Plugin
23  * @package   Laconica
24  * @author    Zach Copley <zach@controlyourself.ca>
25  * @copyright 2009 Control Yourself, Inc.
26  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
27  * @link      http://laconi.ca/
28  */
29
30 require_once INSTALLDIR . '/plugins/FBConnect/FBConnectPlugin.php';
31
32 class FbconnectauthAction extends Action
33 {
34
35     var $fbuid      = null;
36     var $fb_fields  = null;
37
38     function prepare($args) {
39         parent::prepare($args);
40
41         $this->fbuid = getFacebook()->get_loggedin_user();
42         $this->fb_fields = $this->getFacebookFields($this->fbuid,
43             array('first_name', 'last_name', 'name'));
44
45         return true;
46     }
47
48     function handle($args)
49     {
50         parent::handle($args);
51
52         if (common_is_real_login()) {
53             $this->clientError(_('Already logged in.'));
54         } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
55             $token = $this->trimmed('token');
56             if (!$token || $token != common_session_token()) {
57                 $this->showForm(_('There was a problem with your session token. Try again, please.'));
58                 return;
59             }
60             if ($this->arg('create')) {
61                 if (!$this->boolean('license')) {
62                     $this->showForm(_('You can\'t register if you don\'t agree to the license.'),
63                                     $this->trimmed('newname'));
64                     return;
65                 }
66                 $this->createNewUser();
67             } else if ($this->arg('connect')) {
68                 $this->connectUser();
69             } else {
70                 common_debug(print_r($this->args, true), __FILE__);
71                 $this->showForm(_('Something weird happened.'),
72                                 $this->trimmed('newname'));
73             }
74         } else {
75             $this->tryLogin();
76         }
77     }
78
79     function showPageNotice()
80     {
81         if ($this->error) {
82             $this->element('div', array('class' => 'error'), $this->error);
83         } else {
84             $this->element('div', 'instructions',
85                            sprintf(_('This is the first time you\'ve logged into %s so we must connect your Facebook to a local account. You can either create a new account, or connect with your existing account, if you have one.'), common_config('site', 'name')));
86         }
87     }
88
89     function title()
90     {
91         return _('Facebook Account Setup');
92     }
93
94     function showForm($error=null, $username=null)
95     {
96         $this->error = $error;
97         $this->username = $username;
98
99         $this->showPage();
100     }
101
102     function showPage()
103     {
104         parent::showPage();
105     }
106
107     function showContent()
108     {
109         if (!empty($this->message_text)) {
110             $this->element('p', null, $this->message);
111             return;
112         }
113
114         $this->elementStart('form', array('method' => 'post',
115                                           'id' => 'account_connect',
116                                           'action' => common_local_url('fbconnectlogin')));
117         $this->hidden('token', common_session_token());
118         $this->element('h2', null,
119                        _('Create new account'));
120         $this->element('p', null,
121                        _('Create a new user with this nickname.'));
122         $this->input('newname', _('New nickname'),
123                      ($this->username) ? $this->username : '',
124                      _('1-64 lowercase letters or numbers, no punctuation or spaces'));
125         $this->elementStart('p');
126         $this->element('input', array('type' => 'checkbox',
127                                       'id' => 'license',
128                                       'name' => 'license',
129                                       'value' => 'true'));
130         $this->text(_('My text and files are available under '));
131         $this->element('a', array('href' => common_config('license', 'url')),
132                        common_config('license', 'title'));
133         $this->text(_(' except this private data: password, email address, IM address, phone number.'));
134         $this->elementEnd('p');
135         $this->submit('create', _('Create'));
136         $this->element('h2', null,
137                        _('Connect existing account'));
138         $this->element('p', null,
139                        _('If you already have an account, login with your username and password to connect it to your Facebook.'));
140         $this->input('nickname', _('Existing nickname'));
141         $this->password('password', _('Password'));
142         $this->submit('connect', _('Connect'));
143         $this->elementEnd('form');
144     }
145
146     function message($msg)
147     {
148         $this->message_text = $msg;
149         $this->showPage();
150     }
151
152     function createNewUser()
153     {
154
155         if (common_config('site', 'closed')) {
156             $this->clientError(_('Registration not allowed.'));
157             return;
158         }
159
160         $invite = null;
161
162         if (common_config('site', 'inviteonly')) {
163             $code = $_SESSION['invitecode'];
164             if (empty($code)) {
165                 $this->clientError(_('Registration not allowed.'));
166                 return;
167             }
168
169             $invite = Invitation::staticGet($code);
170
171             if (empty($invite)) {
172                 $this->clientError(_('Not a valid invitation code.'));
173                 return;
174             }
175         }
176
177         $nickname = $this->trimmed('newname');
178
179         if (!Validate::string($nickname, array('min_length' => 1,
180                                                'max_length' => 64,
181                                                'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
182             $this->showForm(_('Nickname must have only lowercase letters and numbers and no spaces.'));
183             return;
184         }
185
186         if (!User::allowed_nickname($nickname)) {
187             $this->showForm(_('Nickname not allowed.'));
188             return;
189         }
190
191         if (User::staticGet('nickname', $nickname)) {
192             $this->showForm(_('Nickname already in use. Try another one.'));
193             return;
194         }
195
196         $fullname = trim($this->fb_fields['firstname'] .
197             ' ' . $this->fb_fields['lastname']);
198
199         $args = array('nickname' => $nickname, 'fullname' => $fullname);
200
201         if (!empty($invite)) {
202             $args['code'] = $invite->code;
203         }
204
205         $user = User::register($args);
206
207         $result = $this->flinkUser($user->id, $this->fbuid);
208
209         if (!$result) {
210             $this->serverError(_('Error connecting user to Facebook.'));
211             return;
212         }
213
214         common_set_user($user);
215         common_real_login(true);
216
217         common_debug("Registered new user $user->id from Facebook user $this->fbuid");
218
219         common_redirect(common_local_url('showstream', array('nickname' => $user->nickname)),
220                         303);
221     }
222
223     function connectUser()
224     {
225         $nickname = $this->trimmed('nickname');
226         $password = $this->trimmed('password');
227
228         if (!common_check_user($nickname, $password)) {
229             $this->showForm(_('Invalid username or password.'));
230             return;
231         }
232
233         $user = User::staticGet('nickname', $nickname);
234
235         if ($user) {
236             common_debug("Legit user to connect to Facebook: $nickname");
237         }
238
239         $result = $this->flinkUser($user->id, $this->fbuid);
240
241         if (!$result) {
242             $this->serverError(_('Error connecting user to Facebook.'));
243             return;
244         }
245
246         common_debug("Connected Facebook user $this->fbuid to local user $user->id");
247
248         common_set_user($user);
249         common_real_login(true);
250
251         $this->goHome($user->nickname);
252     }
253
254     function tryLogin()
255     {
256         common_debug("Trying Facebook Login...");
257
258         $flink = Foreign_link::getByForeignID($this->fbuid, FACEBOOK_SERVICE);
259
260         if ($flink) {
261             $user = $flink->getUser();
262
263             if ($user) {
264
265                 common_debug("Logged in Facebook user $flink->foreign_id as user $user->id ($user->nickname)");
266
267                 common_set_user($user);
268                 common_real_login(true);
269                 $this->goHome($user->nickname);
270             }
271
272         } else {
273             $this->showForm(null, $this->bestNewNickname());
274         }
275     }
276
277     function goHome($nickname)
278     {
279         $url = common_get_returnto();
280         if ($url) {
281             // We don't have to return to it again
282             common_set_returnto(null);
283         } else {
284             $url = common_local_url('all',
285                                     array('nickname' =>
286                                           $nickname));
287         }
288
289         common_redirect($url, 303);
290     }
291
292     function flinkUser($user_id, $fbuid)
293     {
294         $flink = new Foreign_link();
295         $flink->user_id = $user_id;
296         $flink->foreign_id = $fbuid;
297         $flink->service = FACEBOOK_SERVICE;
298         $flink->created = common_sql_now();
299
300         $flink_id = $flink->insert();
301
302         return $flink_id;
303     }
304
305     function bestNewNickname()
306     {
307         if (!empty($this->fb_fields['name'])) {
308             $nickname = $this->nicknamize($this->fb_fields['name']);
309             if ($this->isNewNickname($nickname)) {
310                 return $nickname;
311             }
312         }
313
314         // Try the full name
315
316         $fullname = trim($this->fb_fields['firstname'] .
317             ' ' . $this->fb_fields['lastname']);
318
319         if (!empty($fullname)) {
320             $fullname = $this->nicknamize($fullname);
321             if ($this->isNewNickname($fullname)) {
322                 return $fullname;
323             }
324         }
325
326         return null;
327     }
328
329      // Given a string, try to make it work as a nickname
330
331      function nicknamize($str)
332      {
333          $str = preg_replace('/\W/', '', $str);
334          return strtolower($str);
335      }
336
337     function isNewNickname($str)
338     {
339         if (!Validate::string($str, array('min_length' => 1,
340                                           'max_length' => 64,
341                                           'format' => VALIDATE_NUM . VALIDATE_ALPHA_LOWER))) {
342             return false;
343         }
344         if (!User::allowed_nickname($str)) {
345             return false;
346         }
347         if (User::staticGet('nickname', $str)) {
348             return false;
349         }
350         return true;
351     }
352
353     // XXX: Consider moving this to lib/facebookutil.php
354     function getFacebookFields($fb_uid, $fields) {
355         try {
356             $infos = getFacebook()->api_client->users_getInfo($fb_uid, $fields);
357
358             if (empty($infos)) {
359                 return null;
360             }
361             return reset($infos);
362
363         } catch (Exception $e) {
364             error_log("Failure in the api when requesting " . join(",", $fields)
365                   ." on uid " . $fb_uid . " : ". $e->getMessage());
366               return null;
367         }
368     }
369
370 }