~ubuntu-branches/ubuntu/saucy/mediawiki-extensions/saucy

« back to all changes in this revision

Viewing changes to include/SpecialOpenID.body.php

  • Committer: Bazaar Package Importer
  • Author(s): Romain Beauxis
  • Date: 2009-03-25 19:36:16 UTC
  • Revision ID: james.westby@ubuntu.com-20090325193616-wao3b2mgbb0qyv7i
Tags: 1.6
* Updated extensions.
* Added OpenID extension.
* Added README.Debian.
Closes: #516693
* Bumped standards version to 3.8.1
* Bumped compatibility level to 7.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * SpecialOpenID.body.php -- Superclass for all
 
4
 * Copyright 2006,2007 Internet Brands (http://www.internetbrands.com/)
 
5
 * Copyright 2008 by Evan Prodromou (http://evan.prodromou.name/)
 
6
 *
 
7
 *  This program is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License as published by
 
9
 *  the Free Software Foundation; either version 2 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 General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with this program; if not, write to the Free Software
 
19
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
20
 *
 
21
 * @author Evan Prodromou <evan@prodromou.name>
 
22
 * @addtogroup Extensions
 
23
 */
 
24
 
 
25
# FIXME: for login(); figure out better way to share this code
 
26
# between Login and Convert
 
27
 
 
28
require_once("Auth/OpenID/Consumer.php");
 
29
require_once("Auth/OpenID/SReg.php");
 
30
require_once("Auth/OpenID/FileStore.php");
 
31
 
 
32
class SpecialOpenID extends SpecialPage {
 
33
 
 
34
        function getOpenIDStore($storeType, $prefix, $options) {
 
35
            global $wgOut;
 
36
 
 
37
                # FIXME: support other kinds of store
 
38
                # XXX: used to support memc, now use memcached from php-openid
 
39
 
 
40
            switch ($storeType) {
 
41
 
 
42
                 case 'file':
 
43
                        # Auto-create path if it doesn't exist
 
44
                        if (!is_dir($options['path'])) {
 
45
                                if (!mkdir($options['path'], 0770, true)) {
 
46
                                        $wgOut->showErrorPage('openidconfigerror', 'openidconfigerrortext');
 
47
                                        return NULL;
 
48
                                }
 
49
                        }
 
50
                        return new Auth_OpenID_FileStore($options['path']);
 
51
 
 
52
                 default:
 
53
                        $wgOut->showErrorPage('openidconfigerror', 'openidconfigerrortext');
 
54
            }
 
55
        }
 
56
 
 
57
        function xriBase($xri) {
 
58
                if (substr($xri, 0, 6) == 'xri://') {
 
59
                        return substr($xri, 6);
 
60
                } else {
 
61
                        return $xri;
 
62
                }
 
63
        }
 
64
 
 
65
        function xriToUrl($xri) {
 
66
                return 'http://xri.net/' . OpenIDXriBase($xri);
 
67
        }
 
68
 
 
69
        static function OpenIDToUrl($openid) {
 
70
                /* ID is either an URL already or an i-name */
 
71
        if (Auth_Yadis_identifierScheme($openid) == 'XRI') {
 
72
                        return OpenIDXriToUrl($openid);
 
73
                } else {
 
74
                        return $openid;
 
75
                }
 
76
        }
 
77
 
 
78
        function interwikiExpand($openid_url) {
 
79
                # try to make it into a title object
 
80
                $nt = Title::newFromText($openid_url);
 
81
                # If it's got an iw, return that
 
82
                if (!is_null($nt) && !is_null($nt->getInterwiki())
 
83
                        && strlen($nt->getInterwiki()) > 0) {
 
84
                        return $nt->getFullUrl();
 
85
                } else {
 
86
                        return $openid_url;
 
87
                }
 
88
        }
 
89
 
 
90
        static function getUserUrl($user) {
 
91
                $openid_url = null;
 
92
 
 
93
                if ( isset( $user ) && $user->getId() != 0 ) {
 
94
                        global $wgSharedDB, $wgDBprefix;
 
95
                        if ( isset( $wgSharedDB ) ) {
 
96
                                $tableName = "`${wgSharedDB}`.${wgDBprefix}user_openid";
 
97
                        } else {
 
98
                                $tableName = 'user_openid';
 
99
                        }
 
100
 
 
101
                        $dbr = wfGetDB( DB_SLAVE );
 
102
                        $res = $dbr->select(
 
103
                                array( $tableName ),
 
104
                                array( 'uoi_openid' ),
 
105
                                array( 'uoi_user' => $user->getId() ),
 
106
                                __METHOD__
 
107
                        );
 
108
 
 
109
                        # This should return 0 or 1 result, since user is unique
 
110
                        # in the table.
 
111
 
 
112
                        while ( $row = $res->fetchObject() ) {
 
113
                                $openid_url = $row->uoi_openid;
 
114
                        }
 
115
                        $res->free();
 
116
                }
 
117
                return $openid_url;
 
118
        }
 
119
 
 
120
        # Login, Finish
 
121
 
 
122
        function getConsumer() {
 
123
                global $wgOpenIDConsumerStoreType, $wgOpenIDConsumerStorePath;
 
124
 
 
125
                $store = $this->getOpenIDStore($wgOpenIDConsumerStoreType,
 
126
                                                                           'consumer',
 
127
                                                                           array('path' => $wgOpenIDConsumerStorePath));
 
128
 
 
129
                return new Auth_OpenID_Consumer($store);
 
130
        }
 
131
 
 
132
        function fullUrl($title) {
 
133
                $nt = Title::makeTitleSafe(NS_SPECIAL, $title);
 
134
                if (isset($nt)) {
 
135
                        return $nt->getFullURL();
 
136
                } else {
 
137
                        return NULL;
 
138
                }
 
139
        }
 
140
 
 
141
        function scriptUrl($title) {
 
142
                global $wgServer, $wgScript;
 
143
                $nt = Title::makeTitleSafe(NS_SPECIAL, $title);
 
144
                if (isset($nt)) {
 
145
                        $dbkey = wfUrlencode( $nt->getPrefixedDBkey() );
 
146
                        return "{$wgServer}{$wgScript}?title={$dbkey}";
 
147
                } else {
 
148
                        return $url;
 
149
                }
 
150
        }
 
151
 
 
152
        function canLogin($openid_url) {
 
153
 
 
154
                global $wgOpenIDConsumerDenyByDefault, $wgOpenIDConsumerAllow, $wgOpenIDConsumerDeny;
 
155
 
 
156
                if ($this->isLocalUrl($openid_url)) {
 
157
                        return false;
 
158
                }
 
159
 
 
160
                if ($wgOpenIDConsumerDenyByDefault) {
 
161
                        $canLogin = false;
 
162
                        foreach ($wgOpenIDConsumerAllow as $allow) {
 
163
                                if (preg_match($allow, $openid_url)) {
 
164
                                        wfDebug("OpenID: $openid_url matched allow pattern $allow.\n");
 
165
                                        $canLogin = true;
 
166
                                        foreach ($wgOpenIDConsumerDeny as $deny) {
 
167
                                                if (preg_match($deny, $openid_url)) {
 
168
                                                        wfDebug("OpenID: $openid_url matched deny pattern $deny.\n");
 
169
                                                        $canLogin = false;
 
170
                                                        break;
 
171
                                                }
 
172
                                        }
 
173
                                        break;
 
174
                                }
 
175
                        }
 
176
                } else {
 
177
                        $canLogin = true;
 
178
                        foreach ($wgOpenIDConsumerDeny as $deny) {
 
179
                                if (preg_match($deny, $openid_url)) {
 
180
                                        wfDebug("OpenID: $openid_url matched deny pattern $deny.\n");
 
181
                                        $canLogin = false;
 
182
                                        foreach ($wgOpenIDConsumerAllow as $allow) {
 
183
                                                if (preg_match($allow, $openid_url)) {
 
184
                                                        wfDebug("OpenID: $openid_url matched allow pattern $allow.\n");
 
185
                                                        $canLogin = true;
 
186
                                                        break;
 
187
                                                }
 
188
                                        }
 
189
                                        break;
 
190
                                }
 
191
                        }
 
192
                }
 
193
                return $canLogin;
 
194
        }
 
195
 
 
196
        function isLocalUrl($url) {
 
197
 
 
198
                global $wgServer, $wgArticlePath;
 
199
 
 
200
                $pattern = $wgServer . $wgArticlePath;
 
201
                $pattern = str_replace('$1', '(.*)', $pattern);
 
202
                $pattern = str_replace('?', '\?', $pattern);
 
203
 
 
204
                return preg_match('|^' . $pattern . '$|', $url);
 
205
        }
 
206
 
 
207
        # Find the user with the given openid, if any
 
208
 
 
209
        function getUser($openid) {
 
210
                global $wgSharedDB, $wgDBprefix;
 
211
 
 
212
                if (isset($wgSharedDB)) {
 
213
                        $tableName = "`$wgSharedDB`.${wgDBprefix}user_openid";
 
214
                } else {
 
215
                        $tableName = 'user_openid';
 
216
                }
 
217
 
 
218
                $dbr =& wfGetDB( DB_SLAVE );
 
219
                $id = $dbr->selectField($tableName, 'uoi_user',
 
220
                                                                array('uoi_openid' => $openid));
 
221
                if ($id) {
 
222
                        $name = User::whoIs($id);
 
223
                        return User::newFromName($name);
 
224
                } else {
 
225
                        return NULL;
 
226
                }
 
227
        }
 
228
        function login($openid_url, $finish_page = 'OpenIDFinish') {
 
229
 
 
230
                global $wgUser, $wgTrustRoot, $wgOut;
 
231
 
 
232
                # If it's an interwiki link, expand it
 
233
 
 
234
                $openid_url = $this->interwikiExpand($openid_url);
 
235
 
 
236
                # Check if the URL is allowed
 
237
 
 
238
                if (!$this->canLogin($openid_url)) {
 
239
                        $wgOut->showErrorPage('openidpermission', 'openidpermissiontext');
 
240
                        return;
 
241
                }
 
242
 
 
243
                $sk = $wgUser->getSkin();
 
244
 
 
245
                if (isset($wgTrustRoot)) {
 
246
                        $trust_root = $wgTrustRoot;
 
247
                } else {
 
248
                        global $wgArticlePath, $wgServer;
 
249
                        $root_article = str_replace('$1', '', $wgArticlePath);
 
250
                        $trust_root = $wgServer . $root_article;
 
251
                }
 
252
 
 
253
                $consumer = $this->getConsumer();
 
254
 
 
255
                if (!$consumer) {
 
256
                        $wgOut->showErrorPage('openiderror', 'openiderrortext');
 
257
                        return;
 
258
                }
 
259
 
 
260
                # Make sure the user has a session!
 
261
 
 
262
                global $wgSessionStarted;
 
263
 
 
264
                if (!$wgSessionStarted) {
 
265
                        $wgUser->SetupSession();
 
266
                }
 
267
 
 
268
                $auth_request = $consumer->begin($openid_url);
 
269
 
 
270
                // Handle failure status return values.
 
271
                if (!$auth_request) {
 
272
                        $wgOut->showErrorPage('openiderror', 'openiderrortext');
 
273
                        return;
 
274
                }
 
275
 
 
276
                # Check the processed URLs, too
 
277
 
 
278
                $endpoint = $auth_request->endpoint;
 
279
 
 
280
                if (isset($endpoint)) {
 
281
                        # Check if the URL is allowed
 
282
 
 
283
                        if (isset($endpoint->identity_url) && !$this->canLogin($endpoint->identity_url)) {
 
284
                                $wgOut->showErrorPage('openidpermission', 'openidpermissiontext');
 
285
                                return;
 
286
                        }
 
287
 
 
288
                        if (isset($endpoint->delegate) && !$this->canLogin($endpoint->delegate)) {
 
289
                                $wgOut->showErrorPage('openidpermission', 'openidpermissiontext');
 
290
                                return;
 
291
                        }
 
292
                }
 
293
 
 
294
                $sreg_request = Auth_OpenID_SRegRequest::build(
 
295
                                                                                                           // Required
 
296
                                                                                                           array(),
 
297
                                                                                                           // Optional
 
298
                                                                                                           array('nickname','email',
 
299
                                                                                                                         'fullname','language','timezone'));
 
300
 
 
301
                if ($sreg_request) {
 
302
                        $auth_request->addExtension($sreg_request);
 
303
                }
 
304
 
 
305
                $process_url = $this->scriptUrl($finish_page);
 
306
 
 
307
                if ($auth_request->shouldSendRedirect()) {
 
308
                        $redirect_url = $auth_request->redirectURL($trust_root,
 
309
                                                                                                           $process_url);
 
310
                        if (Auth_OpenID::isFailure($redirect_url)) {
 
311
                                displayError("Could not redirect to server: " . $redirect_url->message);
 
312
                        } else {
 
313
                                # OK, now go
 
314
                                $wgOut->redirect($redirect_url);
 
315
                        }
 
316
                } else {
 
317
                        // Generate form markup and render it.
 
318
                        $form_id = 'openid_message';
 
319
                        $form_html = $auth_request->formMarkup($trust_root, $process_url,
 
320
                                                                                                   false, array('id' => $form_id));
 
321
 
 
322
                        // Display an error if the form markup couldn't be generated;
 
323
                        // otherwise, render the HTML.
 
324
                        if (Auth_OpenID::isFailure($form_html)) {
 
325
                                displayError("Could not redirect to server: " . $form_html->message);
 
326
                        } else {
 
327
                                $wgOut->addHTML("<p>" . wfMsg("openidautosubmit") . "</p>");
 
328
                                $wgOut->addHTML($form_html);
 
329
                                $wgOut->addInlineScript("function submitOpenIDForm() {\n document.getElementById(\"".$form_id."\").submit()\n }\nhookEvent(\"load\", submitOpenIDForm);\n");
 
330
                        }
 
331
                }
 
332
        }
 
333
        
 
334
        function setUserUrl($user, $url) {
 
335
                $other = $this->getUserUrl($user);
 
336
                if (isset($other)) {
 
337
                        $this->updateUserUrl($user, $url);
 
338
                } else {
 
339
                        $this->insertUserUrl($user, $url);
 
340
                }
 
341
        }
 
342
 
 
343
        function insertUserUrl($user, $url) {
 
344
                global $wgSharedDB, $wgDBname;
 
345
                $dbw =& wfGetDB( DB_MASTER );
 
346
 
 
347
                if (isset($wgSharedDB)) {
 
348
                        # It would be nicer to get the existing dbname
 
349
                        # and save it, but it's not possible
 
350
                        $dbw->selectDB($wgSharedDB);
 
351
                }
 
352
 
 
353
                $dbw->insert('user_openid', array('uoi_user' => $user->getId(),
 
354
                                                                                  'uoi_openid' => $url));
 
355
 
 
356
                if (isset($wgSharedDB)) {
 
357
                        $dbw->selectDB($wgDBname);
 
358
                }
 
359
        }
 
360
 
 
361
        function updateUserUrl($user, $url) {
 
362
                global $wgSharedDB, $wgDBname;
 
363
                $dbw =& wfGetDB( DB_MASTER );
 
364
 
 
365
                if (isset($wgSharedDB)) {
 
366
                        # It would be nicer to get the existing dbname
 
367
                        # and save it, but it's not possible
 
368
                        $dbw->selectDB($wgSharedDB);
 
369
                }
 
370
 
 
371
                $dbw->set('user_openid', 'uoi_openid', $url,
 
372
                                  'uoi_user = ' . $user->getID());
 
373
 
 
374
                if (isset($wgSharedDB)) {
 
375
                        $dbw->selectDB($wgDBname);
 
376
                }
 
377
        }
 
378
}