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