register.php 16 KB
Newer Older
1
2
<?php
/**
Francois Marier's avatar
Francois Marier committed
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
6
 *
Francois Marier's avatar
Francois Marier committed
7
8
9
10
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
11
 *
Francois Marier's avatar
Francois Marier committed
12
13
14
15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
16
 *
Francois Marier's avatar
Francois Marier committed
17
18
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21
 *
 * @package    mahara
 * @subpackage core
22
 * @author     Catalyst IT Ltd
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25
26
27
28
29
 *
 */

define('INTERNAL', 1);
define('PUBLIC', 1);
30
31
32
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'site');
define('SECTION_PAGE', 'register');
33
require('init.php');
34
require_once('pieforms/pieform.php');
35
require_once('lib/antispam.php');
Martyn Smith's avatar
Martyn Smith committed
36
define('TITLE', get_string('register'));
37
define('SPAM_SCORE', 3);
38
$key = param_alphanum('key', null);
39

40
41
42
43
44
45
46
47
48
49
50
51
/*
 * This page handles three different tasks:
 *   1) Showing a visitor the registration form
 *   2) Telling the visitor to check their e-mail for a message
 *   3) Given a key, display profile information to edit
 *
 * It uses the session to store some state
 */
if (!session_id()) {
    session_start();
}

52
53
// Logged in people can't register. If someone passes a key however, log the 
// user out and see if this key registers someone
Nigel McNie's avatar
Nigel McNie committed
54
if (is_logged_in()) {
55
56
57
58
59
60
    if ($key) {
        $USER->logout();
    }
    else {
        redirect();
    }
61
62
}

63
64
65
66
// Step two of registration (first as it's the easiest): the user has
// registered, show them a screen telling them this.
if (!empty($_SESSION['registered'])) {
    unset($_SESSION['registered']);
67
    die_info(get_string('registeredok', 'auth.internal'));
68
69
}

70
// Step three of registration - given a key register the user
71
if (isset($key)) {
72

73
74
75
76
77
    // Begin the registration form buliding
    if (!$registration = get_record_select('usr_registration', '"key" = ? AND expiry >= ?', array($key, db_format_timestamp(time())))) {
        die_info(get_string('registrationnosuchkey', 'auth.internal'));
    }

78
79
80
81
82
83
    // In case a new session has started, reset the session language
    // to the one selected during registration
    if (!empty($registration->lang)) {
        $SESSION->set('lang', $registration->lang);
    }

84
    function create_registered_user($profilefields=array()) {
85
        global $registration, $SESSION, $USER;
86
        require_once(get_config('libroot') . 'user.php');
87

88
        db_begin();
89
90
91
92

        // Move the user record to the usr table from the registration table
        $registrationid = $registration->id;
        unset($registration->id);
93
        unset($registration->expiry);
94
        if ($expirytime = get_config('defaultaccountlifetime')) {
95
96
            $registration->expiry = db_format_timestamp(time() + $expirytime);
        }
97
        $registration->lastlogin = db_format_timestamp(time());
98
99
100
101
102
103
104
105
106
107
108
109

        $authinstance = get_record('auth_instance', 'institution', $registration->institution, 'authname', 'internal');
        if (false == $authinstance) {
            // TODO: Specify exception
            throw new Exception('No internal auth instance for institution');
        }

        $user = new User();
        $user->active           = 1;
        $user->authinstance     = $authinstance->id;
        $user->firstname        = $registration->firstname;
        $user->lastname         = $registration->lastname;
110
        $user->email            = $registration->email;
111
112
113
        $user->username         = get_new_username($user->firstname . $user->lastname);
        $user->passwordchange   = 1;
        $user->salt             = substr(md5(rand(1000000, 9999999)), 2, 8);
114

115
        create_user($user, $profilefields);
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130
        // If the institution is 'mahara' then don't do anything
        if ($registration->institution != 'mahara') {
            $institutions = get_records_select_array('institution', "name != 'mahara'");

            // If there is only one available, join it without requiring approval
            if (count($institutions) == 1) {
                $user->join_institution($registration->institution);
            }
            // Else, since there are multiple, request to join
            else {
                $user->add_institution_request($registration->institution);
            }
        }

131

132
133
134
        if (!empty($registration->lang) && $registration->lang != 'default') {
            set_account_preference($user->id, 'lang', $registration->lang);
        }
135
136

        // Delete the old registration record
137
138
        delete_records('usr_registration', 'id', $registrationid);

139
140
        db_commit();

141
        // Log the user in and send them to the homepage
142
143
        $USER = new LiveUser();
        $USER->reanimate($user->id, $authinstance->id);
Nigel McNie's avatar
Nigel McNie committed
144
145

        // A special greeting for special people
146
        if (in_array($user->username, array('waawaamilk', 'Mjollnir`', 'Ned', 'richardm', 'fmarier', 'naveg'))) {
Nigel McNie's avatar
Nigel McNie committed
147
148
149
150
151
            $SESSION->add_ok_msg('MAMA!!! Maharababy happy to see you :D :D!');
        }
        else if ($user->username == 'htaccess') {
            $SESSION->add_ok_msg('Welcome B-Quack, htaccess!');
        }
152
153
154
        else {
            $SESSION->add_ok_msg(get_string('registrationcomplete', 'mahara', get_config('sitename')));
        }
155
        $SESSION->set('resetusername', true);
156
        redirect();
157
    }
158
    create_registered_user();
159
160
}

161
162
163

// Default page - show the registration form

164
165
166
167
168
169
170
171
172
173
174
175
// we're in the middle of processing the form, so read the time
// from the form rather than getting a new one
if ($_POST) {
    $time = $_POST['timestamp'];
}
else {
    $time = time();
}

$fields = array('firstname', 'lastname', 'email', 'institution', 'tandc', 'submit', 'invisiblefield', 'invisiblesubmit');
$hashed_fields = hash_fieldnames($fields, $time);

176
177
178
$elements = array(
    'firstname' => array(
        'type' => 'text',
179
        'name' => $hashed_fields['firstname'],
180
181
182
183
184
185
186
        'title' => get_string('firstname'),
        'rules' => array(
            'required' => true
        )
    ),
    'lastname' => array(
        'type' => 'text',
187
        'name' => $hashed_fields['lastname'],
188
189
190
191
192
193
194
        'title' => get_string('lastname'),
        'rules' => array(
            'required' => true
        )
    ),
    'email' => array(
        'type' => 'text',
195
        'name' => $hashed_fields['email'],
196
197
198
199
200
201
202
        'title' => get_string('emailaddress'),
        'rules' => array(
            'required' => true,
            'email' => true
        )
    )
);
203
204
205
$sql = 'SELECT
            i.*
        FROM
206
207
            {institution} i,
            {auth_instance} ai
208
209
        WHERE
            ai.authname = \'internal\' AND
210
211
            ai.institution = i.name AND
            i.registerallowed = 1';
212
213
$institutions = get_records_sql_array($sql, array());

214
215
216
217
218
if (count($institutions) > 1) {
    $options = array();
    foreach ($institutions as $institution) {
        $options[$institution->name] = $institution->displayname;
    }
219
    natcasesort($options);
220
221
    $elements['institution'] = array(
        'type' => 'select',
222
        'name' => $hashed_fields['institution'],
223
        'title' => get_string('institution'),
224
225
226
227
        'options' => $options,
        'rules' => array(
            'required' => true
        )
228
229
    );
}
230
231
232
233
else if ($institutions) { // Only one option - probably mahara ('No Institution') but that's not certain

    $institution = array_shift($institutions);

234
235
    $elements['institution'] = array(
        'type' => 'hidden',
236
        'name' => $hashed_fields['institution'],
237
        'value' => $institution->name
238
239
    );
}
240
241
242
else {
    die_info(get_string('registeringdisallowed'));
}
243
244
245

$elements['tandc'] = array(
    'type' => 'radio',
246
    'name' => $hashed_fields['tandc'],
247
248
    'title' => get_string('iagreetothetermsandconditions', 'auth.internal'),
    'description' => get_string('youmustagreetothetermsandconditions', 'auth.internal'),
249
250
251
    'options' => array(
        'yes' => get_string('yes'),
        'no'  => get_string('no')
252
253
254
255
256
    ),
    'defaultvalue' => 'no',
    'rules' => array(
        'required' => true
    ),
257
258
    'separator' => ' &nbsp; '
);
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
$elements['invisiblefield'] = array(
    'type' => 'text',
    'name' => $hashed_fields['invisiblefield'],
    'title' => get_string('spamtrap'),
    'defaultvalue' => '',
    'class' => 'dontshow',
);
$elements['timestamp'] = array(
    'type' => 'hidden',
    'value' => $time,
);
$elements['invisiblesubmit'] = array(
    'type'  => 'submit',
    'name' => $hashed_fields['invisiblesubmit'],
    'value' => get_string('spamtrap'),
    'class' => 'dontshow',
);
276
$elements['submit'] = array(
277
    'type' => 'submit',
278
    'name' => $hashed_fields['submit'],
279
    'value' => get_string('register'),
280
281
);

282
283
284
285
286
287
288
289
// swap the name and email fields at random
if (rand(0,1)) {
    $firstname = array_shift($elements);
    $lastname = array_shift($elements);
    $email = array_shift($elements);
    array_unshift($elements, $email, $firstname, $lastname);
}

290
291
292
$form = array(
    'name' => 'register',
    'method' => 'post',
293
294
    'plugintype' => 'core',
    'pluginname' => 'register',
295
    'action' => '',
296
    'showdescriptiononerror' => false,
297
    'renderer' => 'table',
298
299
300
    'elements' => $elements
);

301
302
303
304
305
306
/**
 * @todo add note: because the form select thing will eventually enforce
 * that the result for $values['institution'] was in the original lot,
 * and because that only allows authmethods that use 'internal' auth, we
 * can guarantee that the auth method is internal
 */
307
function register_validate(Pieform $form, $values) {
308
    global $SESSION;
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
    $error = false;
    $currenttime = time();
    // read the timestamp field
    $timestamp = $values['timestamp'];
    // recompute the field names
    $fields = array('firstname', 'lastname', 'email', 'institution', 'tandc', 'submit', 'invisiblefield', 'invisiblesubmit');
    $hashed = hash_fieldnames($fields, $timestamp);
    // make sure the submission is less than a day, and more than 5 seconds old
    if ($currenttime - $timestamp < 5 || $currenttime - $timestamp > 86400) {
        $error = true;
    }
    // make sure the real submit button was used. If it wasn't, it won't exist.
    elseif (!isset($values[$hashed['submit']]) || isset($values[$hashed['invisiblesubmit']])) {
        $error = true;
    }
    // make sure the invisible field is empty
    elseif (!isset($values[$hashed['invisiblefield']]) || $values[$hashed['invisiblefield']] != '') {
        $error = true;
    }
    // make sure all the other data fields exist
    elseif (!(isset($values[$hashed['firstname']]) && isset($values[$hashed['lastname']]) &&
        isset($values[$hashed['email']]) && isset($values[$hashed['tandc']]) &&
        isset($values[$hashed['institution']]))) {
        $error = true;
    }
    else {
        $spamtrap = new_spam_trap(array(
            array(
                'type' => 'name',
                'value' => $values[$hashed['firstname']],
            ),
            array(
                'type' => 'name',
                'value' => $values[$hashed['lastname']],
            ),
            array(
                'type' => 'email',
                'value' => $values[$hashed['email']],
            ),
        ));
        if ($spamtrap->is_spam()) {
            $error = true;
        }
    }
    if ($error) { 
        $msg = get_string('formerror');
        $emailcontact = get_config('emailcontact');
        if (!empty($emailcontact)) {
            $msg .= ' ' . get_string('formerroremail', 'mahara', $emailcontact, $emailcontact);
        }
        $SESSION->add_error_msg($msg);
        $form->set_error($hashed['submit'], '');
    }
    $institution = $values[$hashed['institution']];
363
    safe_require('auth', 'internal');
364
365
366

    // First name and last name must contain at least one non whitespace
    // character, so that there's something to read
367
368
    if (!$form->get_error($hashed['firstname']) && !preg_match('/\S/', $values[$hashed['firstname']])) {
        $form->set_error($hashed['firstname'], $form->i18n('required'));
369
370
    }

371
372
    if (!$form->get_error($hashed['lastname']) && !preg_match('/\S/', $values[$hashed['lastname']])) {
        $form->set_error($hashed['lastname'], $form->i18n('required'));
373
374
375
    }

    // The e-mail address cannot already be in the system
376
377
378
379
    if (!$form->get_error($hashed['email'])
        && (record_exists('usr', 'email', $values[$hashed['email']])
        || record_exists('artefact_internal_profile_email', 'email', $values[$hashed['email']]))) {
        $form->set_error($hashed['email'], get_string('emailalreadytaken', 'auth.internal'));
380
381
382
    }
    
    // If the user hasn't agreed to the terms and conditions, don't bother
383
384
    if ($values[$hashed['tandc']] != 'yes') {
        $form->set_error($hashed['tandc'], get_string('youmaynotregisterwithouttandc', 'auth.internal'));
385
    }
386

387
    $institution = get_record_sql('
388
        SELECT 
389
            i.name, i.maxuseraccounts, i.registerallowed, COUNT(u.id)
390
391
392
393
394
395
        FROM {institution} i
            LEFT OUTER JOIN {usr_institution} ui ON ui.institution = i.name
            LEFT OUTER JOIN {usr} u ON (ui.usr = u.id AND u.deleted = 0)
        WHERE
            i.name = ?
        GROUP BY
396
            i.name, i.maxuseraccounts, i.registerallowed', array($institution));
397

398
    if (!empty($institution->maxuseraccounts) && $institution->count >= $institution->maxuseraccounts) {
399
        $form->set_error($hashed['institution'], get_string('institutionfull'));
400
401
    }

402
    if (!$institution->registerallowed) {
403
        $form->set_error($hashed['institution'], get_string('registrationnotallowed'));
404
405
    }

406
407
}

408
function register_submit(Pieform $form, $values) {
409
    global $SESSION;
410
411
412
413
414
415
416
417
418
419
420
421
    // read the timestamp field
    $timestamp = $values['timestamp'];
    // recompute the field names
    $fields = array('firstname', 'lastname', 'email', 'institution', 'tandc', 'submit', 'invisiblefield', 'invisiblesubmit');
    $hashed = hash_fieldnames($fields, $timestamp);

    $record_values = array(
        'firstname' => $values[$hashed['firstname']],
        'lastname' => $values[$hashed['lastname']],
        'email' => $values[$hashed['email']],
        'institution' => $values[$hashed['institution']],
    );
422
423
424
425

    // store password encrypted
    // don't die_info, since reloading the page shows the login form.
    // instead, redirect to some other page that says this
426
    safe_require('auth', 'internal');
427
    $record_values['key']   = get_random_key();
428
    // @todo the expiry date should be configurable
429
430
    $record_values['expiry'] = db_format_timestamp(time() + 86400);
    $record_values['lang'] = $SESSION->get('lang');
431
    try {
432
        insert_record('usr_registration', $record_values);
433

434
        $user =(object) $record_values;
435
        $user->admin = 0;
436
        $user->staff = 0;
437
        email_user($user, null,
438
            get_string('registeredemailsubject', 'auth.internal', get_config('sitename')),
439
440
            get_string('registeredemailmessagetext', 'auth.internal', $record_values['firstname'], get_config('sitename'), get_config('wwwroot'), $record_values['key'], get_config('sitename')),
            get_string('registeredemailmessagehtml', 'auth.internal', $record_values['firstname'], get_config('sitename'), get_config('wwwroot'), $record_values['key'], get_config('wwwroot'), $record_values['key'], get_config('sitename')));
441
442
    }
    catch (EmailException $e) {
443
        log_warn($e);
444
        die_info(get_string('registrationunsuccessful', 'auth.internal'));
445
446
    }
    catch (SQLException $e) {
447
        log_warn($e);
448
        die_info(get_string('registrationunsuccessful', 'auth.internal'));
449
450
451
452
453
    }

    // Add a marker in the session to say that the user has registered
    $_SESSION['registered'] = true;

454
    redirect('/register.php');
455
456
}

457
$smarty = smarty();
458
$smarty->assign('register_form', pieform($form));
459
$smarty->assign('PAGEHEADING', hsc(get_string('register')));
460
461
462
$smarty->display('register.tpl');

?>