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