]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - actions/userauthorization.php
Merge commit 'brion/searchfix' into 0.9.x
[quix0rs-gnu-social.git] / actions / userauthorization.php
1 <?php
2 /**
3  * Let the user authorize a remote subscription request
4  *
5  * PHP version 5
6  *
7  * @category Action
8  * @package  Laconica
9  * @author   Evan Prodromou <evan@controlyourself.ca>
10  * @author   Robin Millette <millette@controlyourself.ca>
11  * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
12  * @link     http://laconi.ca/
13  *
14  * Laconica - a distributed open-source microblogging tool
15  * Copyright (C) 2008, 2009, Control Yourself, Inc.
16  *
17  * This program is free software: you can redistribute it and/or modify
18  * it under the terms of the GNU Affero General Public License as published by
19  * the Free Software Foundation, either version 3 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU Affero General Public License for more details.
26  *
27  * You should have received a copy of the GNU Affero General Public License
28  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
29  */
30
31 if (!defined('LACONICA')) {
32     exit(1);
33 }
34
35 require_once INSTALLDIR.'/lib/omb.php';
36 require_once INSTALLDIR.'/extlib/libomb/service_provider.php';
37 require_once INSTALLDIR.'/extlib/libomb/profile.php';
38 define('TIMESTAMP_THRESHOLD', 300);
39
40 class UserauthorizationAction extends Action
41 {
42     var $error;
43     var $params;
44
45     function handle($args)
46     {
47         parent::handle($args);
48
49         if ($_SERVER['REQUEST_METHOD'] == 'POST') {
50             /* Use a session token for CSRF protection. */
51             $token = $this->trimmed('token');
52             if (!$token || $token != common_session_token()) {
53                 $srv = $this->getStoredParams();
54                 $this->showForm($srv->getRemoteUser(), _('There was a problem ' .
55                                         'with your session token. Try again, ' .
56                                         'please.'));
57                 return;
58             }
59             /* We've shown the form, now post user's choice. */
60             $this->sendAuthorization();
61         } else {
62             if (!common_logged_in()) {
63                 /* Go log in, and then come back. */
64                 common_set_returnto($_SERVER['REQUEST_URI']);
65
66                 if (!common_config('site', 'openidonly')) {
67                     common_redirect(common_local_url('login'));
68                 } else {
69                     common_redirect(common_local_url('openidlogin'));
70                 }
71                 return;
72             }
73
74             $user    = common_current_user();
75             $profile = $user->getProfile();
76             if (!$profile) {
77                 common_log_db_error($user, 'SELECT', __FILE__);
78                 $this->serverError(_('User without matching profile'));
79                 return;
80             }
81
82             /* TODO: If no token is passed the user should get a prompt to enter
83                it according to OAuth Core 1.0. */
84             try {
85                 $this->validateOmb();
86                 $srv = new OMB_Service_Provider(
87                         profile_to_omb_profile($user->uri, $profile),
88                         omb_oauth_datastore());
89
90                 $remote_user = $srv->handleUserAuth();
91             } catch (Exception $e) {
92                 $this->clearParams();
93                 $this->clientError($e->getMessage());
94                 return;
95             }
96
97             $this->storeParams($srv);
98             $this->showForm($remote_user);
99         }
100     }
101
102     function showForm($params, $error=null)
103     {
104         $this->params = $params;
105         $this->error  = $error;
106         $this->showPage();
107     }
108
109     function title()
110     {
111         return _('Authorize subscription');
112     }
113
114     function showPageNotice()
115     {
116         $this->element('p', null, _('Please check these details to make sure '.
117                                     'that you want to subscribe to this ' .
118                                     'user’s notices. If you didn’t just ask ' .
119                                     'to subscribe to someone’s notices, '.
120                                     'click “Reject”.'));
121     }
122
123     function showContent()
124     {
125         $params = $this->params;
126
127         $nickname = $params->getNickname();
128         $profile  = $params->getProfileURL();
129         $license  = $params->getLicenseURL();
130         $fullname = $params->getFullname();
131         $homepage = $params->getHomepage();
132         $bio      = $params->getBio();
133         $location = $params->getLocation();
134         $avatar   = $params->getAvatarURL();
135
136         $this->elementStart('div', array('class' => 'profile'));
137         $this->elementStart('div', 'entity_profile vcard');
138         $this->elementStart('a', array('href' => $profile,
139                                             'class' => 'url'));
140         if ($avatar) {
141             $this->element('img', array('src' => $avatar,
142                                         'class' => 'photo avatar',
143                                         'width' => AVATAR_PROFILE_SIZE,
144                                         'height' => AVATAR_PROFILE_SIZE,
145                                         'alt' => $nickname));
146         }
147         $hasFN = ($fullname !== '') ? 'nickname' : 'fn nickname';
148         $this->elementStart('span', $hasFN);
149         $this->raw($nickname);
150         $this->elementEnd('span');
151         $this->elementEnd('a');
152
153         if (!is_null($fullname)) {
154             $this->elementStart('dl', 'entity_fn');
155             $this->elementStart('dd');
156             $this->elementStart('span', 'fn');
157             $this->raw($fullname);
158             $this->elementEnd('span');
159             $this->elementEnd('dd');
160             $this->elementEnd('dl');
161         }
162         if (!is_null($location)) {
163             $this->elementStart('dl', 'entity_location');
164             $this->element('dt', null, _('Location'));
165             $this->elementStart('dd', 'label');
166             $this->raw($location);
167             $this->elementEnd('dd');
168             $this->elementEnd('dl');
169         }
170
171         if (!is_null($homepage)) {
172             $this->elementStart('dl', 'entity_url');
173             $this->element('dt', null, _('URL'));
174             $this->elementStart('dd');
175             $this->elementStart('a', array('href' => $homepage,
176                                                 'class' => 'url'));
177             $this->raw($homepage);
178             $this->elementEnd('a');
179             $this->elementEnd('dd');
180             $this->elementEnd('dl');
181         }
182
183         if (!is_null($bio)) {
184             $this->elementStart('dl', 'entity_note');
185             $this->element('dt', null, _('Note'));
186             $this->elementStart('dd', 'note');
187             $this->raw($bio);
188             $this->elementEnd('dd');
189             $this->elementEnd('dl');
190         }
191
192         if (!is_null($license)) {
193             $this->elementStart('dl', 'entity_license');
194             $this->element('dt', null, _('License'));
195             $this->elementStart('dd', 'license');
196             $this->element('a', array('href' => $license,
197                                       'class' => 'license'),
198                            $license);
199             $this->elementEnd('dd');
200             $this->elementEnd('dl');
201         }
202         $this->elementEnd('div');
203
204         $this->elementStart('div', 'entity_actions');
205         $this->elementStart('ul');
206         $this->elementStart('li', 'entity_subscribe');
207         $this->elementStart('form', array('method' => 'post',
208                                           'id' => 'userauthorization',
209                                           'class' => 'form_user_authorization',
210                                           'name' => 'userauthorization',
211                                           'action' => common_local_url(
212                                                          'userauthorization')));
213         $this->hidden('token', common_session_token());
214
215         $this->submit('accept', _('Accept'), 'submit accept', null,
216                       _('Subscribe to this user'));
217         $this->submit('reject', _('Reject'), 'submit reject', null,
218                       _('Reject this subscription'));
219         $this->elementEnd('form');
220         $this->elementEnd('li');
221         $this->elementEnd('ul');
222         $this->elementEnd('div');
223         $this->elementEnd('div');
224     }
225
226     function sendAuthorization()
227     {
228         $srv = $this->getStoredParams();
229
230         if (is_null($srv)) {
231             $this->clientError(_('No authorization request!'));
232             return;
233         }
234
235         $accepted = $this->arg('accept');
236         try {
237             list($val, $token) = $srv->continueUserAuth($accepted);
238         } catch (Exception $e) {
239             $this->clientError($e->getMessage());
240             return;
241         }
242         if ($val !== false) {
243             common_redirect($val, 303);
244         } elseif ($accepted) {
245             $this->showAcceptMessage($token);
246         } else {
247             $this->showRejectMessage();
248         }
249     }
250
251     function showAcceptMessage($tok)
252     {
253         common_show_header(_('Subscription authorized'));
254         $this->element('p', null,
255                        _('The subscription has been authorized, but no '.
256                          'callback URL was passed. Check with the site’s ' .
257                          'instructions for details on how to authorize the ' .
258                          'subscription. Your subscription token is:'));
259         $this->element('blockquote', 'token', $tok);
260         common_show_footer();
261     }
262
263     function showRejectMessage()
264     {
265         common_show_header(_('Subscription rejected'));
266         $this->element('p', null,
267                        _('The subscription has been rejected, but no '.
268                          'callback URL was passed. Check with the site’s ' .
269                          'instructions for details on how to fully reject ' .
270                          'the subscription.'));
271         common_show_footer();
272     }
273
274     function storeParams($params)
275     {
276         common_ensure_session();
277         $_SESSION['userauthorizationparams'] = serialize($params);
278     }
279
280     function clearParams()
281     {
282         common_ensure_session();
283         unset($_SESSION['userauthorizationparams']);
284     }
285
286     function getStoredParams()
287     {
288         common_ensure_session();
289         $params = unserialize($_SESSION['userauthorizationparams']);
290         return $params;
291     }
292
293     function validateOmb()
294     {
295         $listener = $_GET['omb_listener'];
296         $listenee = $_GET['omb_listenee'];
297         $nickname = $_GET['omb_listenee_nickname'];
298         $profile  = $_GET['omb_listenee_profile'];
299
300         $user = User::staticGet('uri', $listener);
301         if (!$user) {
302             throw new Exception(sprintf(_('Listener URI ‘%s’ not found here'),
303                                         $listener));
304         }
305
306         if (strlen($listenee) > 255) {
307             throw new Exception(sprintf(_('Listenee URI ‘%s’ is too long.'),
308                                         $listenee));
309         }
310
311         $other = User::staticGet('uri', $listenee);
312         if ($other) {
313             throw new Exception(sprintf(_('Listenee URI ‘%s’ is a local user.'),
314                                         $listenee));
315         }
316
317         $remote = Remote_profile::staticGet('uri', $listenee);
318         if ($remote) {
319             $sub             = new Subscription();
320             $sub->subscriber = $user->id;
321             $sub->subscribed = $remote->id;
322             if ($sub->find(true)) {
323                 throw new Exception('You are already subscribed to this user.');
324             }
325         }
326
327         if ($profile == common_profile_url($nickname)) {
328             throw new Exception(sprintf(_('Profile URL ‘%s’ is for a local user.'),
329                                         $profile));
330
331         }
332
333         $license      = $_GET['omb_listenee_license'];
334         $site_license = common_config('license', 'url');
335         if (!common_compatible_license($license, $site_license)) {
336             throw new Exception(sprintf(_('Listenee stream license ‘%s’ is not ' .
337                                           'compatible with site license ‘%s’.'),
338                                         $license, $site_license));
339         }
340
341         $avatar = $_GET['omb_listenee_avatar'];
342         if ($avatar) {
343             if (!common_valid_http_url($avatar) || strlen($avatar) > 255) {
344                 throw new Exception(sprintf(_('Avatar URL ‘%s’ is not valid.'),
345                                             $avatar));
346             }
347             $size = @getimagesize($avatar);
348             if (!$size) {
349                 throw new Exception(sprintf(_('Can’t read avatar URL ‘%s’.'),
350                                             $avatar));
351             }
352             if (!in_array($size[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG,
353                                           IMAGETYPE_PNG))) {
354                 throw new Exception(sprintf(_('Wrong image type for avatar URL '.
355                                               '‘%s’.'), $avatar));
356             }
357         }
358     }
359 }