]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/OpenID/OpenIDPlugin.php
Merge branch 'testing' of git@gitorious.org:statusnet/mainline into 0.9.x
[quix0rs-gnu-social.git] / plugins / OpenID / OpenIDPlugin.php
1 <?php
2 /**
3  * StatusNet, the distributed open-source microblogging tool
4  *
5  * PHP version 5
6  *
7  * LICENCE: This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  * @category  Plugin
21  * @package   StatusNet
22  * @author    Evan Prodromou <evan@status.net>
23  * @copyright 2009 StatusNet, Inc.
24  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
25  * @link      http://status.net/
26  */
27
28 if (!defined('STATUSNET')) {
29     exit(1);
30 }
31
32 /**
33  * Plugin for OpenID authentication and identity
34  *
35  * This class enables consumer support for OpenID, the distributed authentication
36  * and identity system.
37  *
38  * @category Plugin
39  * @package  StatusNet
40  * @author   Evan Prodromou <evan@status.net>
41  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
42  * @link     http://status.net/
43  * @link     http://openid.net/
44  */
45
46 class OpenIDPlugin extends Plugin
47 {
48     /**
49      * Initializer for the plugin.
50      */
51
52     function __construct()
53     {
54         parent::__construct();
55     }
56
57     /**
58      * Add OpenID-related paths to the router table
59      *
60      * Hook for RouterInitialized event.
61      *
62      * @param Net_URL_Mapper $m URL mapper
63      *
64      * @return boolean hook return
65      */
66
67     function onStartInitializeRouter($m)
68     {
69         $m->connect('main/openid', array('action' => 'openidlogin'));
70         $m->connect('main/openidtrust', array('action' => 'openidtrust'));
71         $m->connect('settings/openid', array('action' => 'openidsettings'));
72         $m->connect('index.php?action=finishopenidlogin',
73                     array('action' => 'finishopenidlogin'));
74         $m->connect('index.php?action=finishaddopenid',
75                     array('action' => 'finishaddopenid'));
76         $m->connect('main/openidserver', array('action' => 'openidserver'));
77
78         return true;
79     }
80
81     /**
82      * Public XRDS output hook
83      *
84      * Puts the bits of code needed by some OpenID providers to show
85      * we're good citizens.
86      *
87      * @param Action       $action         Action being executed
88      * @param XMLOutputter &$xrdsOutputter Output channel
89      *
90      * @return boolean hook return
91      */
92
93     function onEndPublicXRDS($action, &$xrdsOutputter)
94     {
95         $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
96                                                   'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
97                                                   'version' => '2.0'));
98         $xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
99         //consumer
100         foreach (array('finishopenidlogin', 'finishaddopenid') as $finish) {
101             $xrdsOutputter->showXrdsService(Auth_OpenID_RP_RETURN_TO_URL_TYPE,
102                                             common_local_url($finish));
103         }
104         //provider
105         $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/server',
106                                         common_local_url('openidserver'),
107                                         null,
108                                         null,
109                                         'http://specs.openid.net/auth/2.0/identifier_select');
110         $xrdsOutputter->elementEnd('XRD');
111     }
112
113     /**
114      * User XRDS output hook
115      *
116      * Puts the bits of code needed to discover OpenID endpoints.
117      *
118      * @param Action       $action         Action being executed
119      * @param XMLOutputter &$xrdsOutputter Output channel
120      *
121      * @return boolean hook return
122      */
123
124     function onEndUserXRDS($action, &$xrdsOutputter)
125     {
126         $xrdsOutputter->elementStart('XRD', array('xmlns' => 'xri://$xrd*($v*2.0)',
127                                                   'xml:id' => 'openid',
128                                                   'xmlns:simple' => 'http://xrds-simple.net/core/1.0',
129                                                   'version' => '2.0'));
130         $xrdsOutputter->element('Type', null, 'xri://$xrds*simple');
131
132         //consumer
133         $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/return_to',
134                                         common_local_url('finishopenidlogin'));
135
136         //provider
137         $xrdsOutputter->showXrdsService('http://specs.openid.net/auth/2.0/signon',
138                                         common_local_url('openidserver'),
139                                         null,
140                                         null,
141                                         common_profile_url($action->user->nickname));
142         $xrdsOutputter->elementEnd('XRD');
143     }
144
145     /**
146      * Menu item for login
147      *
148      * @param Action &$action Action being executed
149      *
150      * @return boolean hook return
151      */
152
153     function onEndLoginGroupNav(&$action)
154     {
155         $action_name = $action->trimmed('action');
156
157         $action->menuItem(common_local_url('openidlogin'),
158                           _m('OpenID'),
159                           _m('Login or register with OpenID'),
160                           $action_name === 'openidlogin');
161
162         return true;
163     }
164
165     /**
166      * Menu item for OpenID admin
167      *
168      * @param Action &$action Action being executed
169      *
170      * @return boolean hook return
171      */
172
173     function onEndAccountSettingsNav(&$action)
174     {
175         $action_name = $action->trimmed('action');
176
177         $action->menuItem(common_local_url('openidsettings'),
178                           _m('OpenID'),
179                           _m('Add or remove OpenIDs'),
180                           $action_name === 'openidsettings');
181
182         return true;
183     }
184
185     /**
186      * Autoloader
187      *
188      * Loads our classes if they're requested.
189      *
190      * @param string $cls Class requested
191      *
192      * @return boolean hook return
193      */
194
195     function onAutoload($cls)
196     {
197         switch ($cls)
198         {
199         case 'OpenidloginAction':
200         case 'FinishopenidloginAction':
201         case 'FinishaddopenidAction':
202         case 'XrdsAction':
203         case 'PublicxrdsAction':
204         case 'OpenidsettingsAction':
205         case 'OpenidserverAction':
206         case 'OpenidtrustAction':
207             require_once INSTALLDIR.'/plugins/OpenID/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
208             return false;
209         case 'User_openid':
210             require_once INSTALLDIR.'/plugins/OpenID/User_openid.php';
211             return false;
212         case 'User_openid_trustroot':
213             require_once INSTALLDIR.'/plugins/OpenID/User_openid_trustroot.php';
214             return false;
215         default:
216             return true;
217         }
218     }
219
220     /**
221      * Sensitive actions
222      *
223      * These actions should use https when SSL support is 'sometimes'
224      *
225      * @param Action  $action Action to form an URL for
226      * @param boolean &$ssl   Whether to mark it for SSL
227      *
228      * @return boolean hook return
229      */
230
231     function onSensitiveAction($action, &$ssl)
232     {
233         switch ($action)
234         {
235         case 'finishopenidlogin':
236         case 'finishaddopenid':
237             $ssl = true;
238             return false;
239         default:
240             return true;
241         }
242     }
243
244     /**
245      * Login actions
246      *
247      * These actions should be visible even when the site is marked private
248      *
249      * @param Action  $action Action to show
250      * @param boolean &$login Whether it's a login action
251      *
252      * @return boolean hook return
253      */
254
255     function onLoginAction($action, &$login)
256     {
257         switch ($action)
258         {
259         case 'openidlogin':
260         case 'finishopenidlogin':
261         case 'openidserver':
262             $login = true;
263             return false;
264         default:
265             return true;
266         }
267     }
268
269     /**
270      * We include a <meta> element linking to the userxrds page, for OpenID
271      * client-side authentication.
272      *
273      * @param Action $action Action being shown
274      *
275      * @return void
276      */
277
278     function onEndShowHeadElements($action)
279     {
280         if ($action instanceof ShowstreamAction) {
281             $action->element('link', array('rel' => 'openid2.provider',
282                                            'href' => common_local_url('openidserver')));
283             $action->element('link', array('rel' => 'openid2.local_id',
284                                            'href' => $action->profile->profileurl));
285             $action->element('link', array('rel' => 'openid.server',
286                                            'href' => common_local_url('openidserver')));
287             $action->element('link', array('rel' => 'openid.delegate',
288                                            'href' => $action->profile->profileurl));
289         }
290         return true;
291     }
292
293     /**
294      * Redirect to OpenID login if they have an OpenID
295      *
296      * @param Action $action Action being executed
297      * @param User   $user   User doing the action
298      *
299      * @return boolean whether to continue
300      */
301
302     function onRedirectToLogin($action, $user)
303     {
304         if (!empty($user) && User_openid::hasOpenID($user->id)) {
305             common_redirect(common_local_url('openidlogin'), 303);
306             return false;
307         }
308         return true;
309     }
310
311     /**
312      * Show some extra instructions for using OpenID
313      *
314      * @param Action $action Action being executed
315      *
316      * @return boolean hook value
317      */
318
319     function onEndShowPageNotice($action)
320     {
321         $name = $action->trimmed('action');
322
323         switch ($name)
324         {
325         case 'register':
326             if (common_logged_in()) {
327                 $instr = '(Have an [OpenID](http://openid.net/)? ' .
328                   '[Add an OpenID to your account](%%action.openidsettings%%)!';
329             } else {
330                 $instr = '(Have an [OpenID](http://openid.net/)? ' .
331                   'Try our [OpenID registration]'.
332                   '(%%action.openidlogin%%)!)';
333             }
334             break;
335         case 'login':
336             $instr = '(Have an [OpenID](http://openid.net/)? ' .
337               'Try our [OpenID login]'.
338               '(%%action.openidlogin%%)!)';
339             break;
340         default:
341             return true;
342         }
343
344         $output = common_markup_to_html($instr);
345         $action->raw($output);
346         return true;
347     }
348
349     /**
350      * Load our document if requested
351      *
352      * @param string &$title  Title to fetch
353      * @param string &$output HTML to output
354      *
355      * @return boolean hook value
356      */
357
358     function onStartLoadDoc(&$title, &$output)
359     {
360         if ($title == 'openid') {
361             $filename = INSTALLDIR.'/plugins/OpenID/doc-src/openid';
362
363             $c      = file_get_contents($filename);
364             $output = common_markup_to_html($c);
365             return false; // success!
366         }
367
368         return true;
369     }
370
371     /**
372      * Add our document to the global menu
373      *
374      * @param string $title   Title being fetched
375      * @param string &$output HTML being output
376      *
377      * @return boolean hook value
378      */
379
380     function onEndLoadDoc($title, &$output)
381     {
382         if ($title == 'help') {
383             $menuitem = '* [OpenID](%%doc.openid%%) - what OpenID is and how to use it with this service';
384
385             $output .= common_markup_to_html($menuitem);
386         }
387
388         return true;
389     }
390
391     /**
392      * Data definitions
393      *
394      * Assure that our data objects are available in the DB
395      *
396      * @return boolean hook value
397      */
398
399     function onCheckSchema()
400     {
401         $schema = Schema::get();
402         $schema->ensureTable('user_openid',
403                              array(new ColumnDef('canonical', 'varchar',
404                                                  '255', false, 'PRI'),
405                                    new ColumnDef('display', 'varchar',
406                                                  '255', false, 'UNI'),
407                                    new ColumnDef('user_id', 'integer',
408                                                  null, false, 'MUL'),
409                                    new ColumnDef('created', 'datetime',
410                                                  null, false),
411                                    new ColumnDef('modified', 'timestamp')));
412         $schema->ensureTable('user_openid_trustroot',
413                              array(new ColumnDef('trustroot', 'varchar',
414                                                  '255', false, 'PRI'),
415                                    new ColumnDef('user_id', 'integer',
416                                                  null, false, 'PRI'),
417                                    new ColumnDef('created', 'datetime',
418                                                  null, false),
419                                    new ColumnDef('modified', 'timestamp')));
420         return true;
421     }
422
423     /**
424      * Add our tables to be deleted when a user is deleted
425      *
426      * @param User  $user    User being deleted
427      * @param array &$tables Array of table names
428      *
429      * @return boolean hook value
430      */
431
432     function onUserDeleteRelated($user, &$tables)
433     {
434         $tables[] = 'User_openid';
435         $tables[] = 'User_openid_trustroot';
436         return true;
437     }
438
439     /**
440      * Add our version information to output
441      *
442      * @param array &$versions Array of version-data arrays
443      *
444      * @return boolean hook value
445      */
446
447     function onPluginVersion(&$versions)
448     {
449         $versions[] = array('name' => 'OpenID',
450                             'version' => STATUSNET_VERSION,
451                             'author' => 'Evan Prodromou, Craig Andrews',
452                             'homepage' => 'http://status.net/wiki/Plugin:OpenID',
453                             'rawdescription' =>
454                             _m('Use <a href="http://openid.net/">OpenID</a> to login to the site.'));
455         return true;
456     }
457 }