1
2
3
4 """
5 Enables the user registration and login system.
6
7 @package user
8 @see <a href='http://drupy.net'>Drupy Homepage</a>
9 @see <a href='http://drupal.org'>Drupal Homepage</a>
10 @note Drupy is a port of the Drupal project.
11 @note This file was ported from Drupal's modules/user/user.module
12 @author Brendon Crawford
13 @copyright 2008 Brendon Crawford
14 @contact message144 at users dot sourceforge dot net
15 @created 2008-01-10
16 @version 0.1
17 @note License:
18
19 This program is free software; you can redistribute it and/or
20 modify it under the terms of the GNU General Public License
21 as published by the Free Software Foundation; either version 2
22 of the License, or (at your option) any later version.
23
24 This program is distributed in the hope that it will be useful,
25 but WITHOUT ANY WARRANTY; without even the implied warranty of
26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 GNU General Public License for more details.
28
29 You should have received a copy of the GNU General Public License
30 along with this program; if not, write to:
31
32 The Free Software Foundation, Inc.,
33 51 Franklin Street, Fifth Floor,
34 Boston, MA 02110-1301,
35 USA
36 """
37
38 __version__ = "$Revision: 1 $"
39
40 from lib.drupy import DrupyPHP as php
41 from lib.drupy import DrupyImport
42
43 from includes import common as lib_common
44 from includes import path as lib_path
45 from includes import database as lib_database
46 from includes import bootstrap as lib_bootstrap
47 from includes import plugin as lib_plugin
48
49
50
51
52 USERNAME_MAX_LENGTH = 60
53
54
55
56
57 EMAIL_MAX_LENGTH = 64
58
59
74
75
76
77
78
79
80
82 return {
83 'user_picture' : {
84 'arguments' : {'account' : None},
85 'template' : 'user-picture'
86 },
87 'user_profile' : {
88 'arguments' : {'account' : None},
89 'template' : 'user-profile',
90 'file' : 'user.pages.inc'
91 },
92 'user_profile_category' : {
93 'arguments' : {'element' : None},
94 'template' : 'user-profile-category',
95 'file' : 'user.pages.inc'
96 },
97 'user_profile_item' : {
98 'arguments' : {'element' : None},
99 'template' : 'user-profile-item',
100 'file' : 'user.pages.inc'
101 },
102 'user_list' : {
103 'arguments' : {'users' : None, 'title' : None}
104 },
105 'user_admin_perm' : {
106 'arguments' : {'form' : None},
107 'file' : 'user.admin.inc'
108 },
109 'user_admin_new_role' : {
110 'arguments' : {'form' : None},
111 'file' : 'user.admin.inc'
112 },
113 'user_admin_account' : {
114 'arguments' : {'form' : None},
115 'file' : 'user.admin.inc'
116 },
117 'user_filter_form' : {
118 'arguments' : {'form' : None},
119 'file' : 'user.admin.inc'
120 },
121 'user_filters' : {
122 'arguments' : {'form' : None},
123 'file' : 'user.admin.inc'
124 },
125 'user_signature' : {
126 'arguments' : {'signature' : None},
127 },
128 }
129
130
131
132
134 result = lib_database.query(\
135 "SELECT uid FROM {authmap} WHERE authname = '%s'", authname)
136 this_user = lib_database.fetch_array(result)
137 if (this_user):
138 return lib_plugin.plugins['user'].load(this_user)
139 else:
140 return False
141
142
143
145 """
146 Perform standard Drupal login operations for a user object.
147
148 The user object must already be authenticated. This function verifies
149 that the user account is not blocked and then performs the login,
150 updates the login timestamp in the database, invokes hook_user('login'),
151 and regenerates the session.
152
153 @param account
154 An authenticated user object to be set as the currently logged
155 in user.
156 @param edit
157 The array of form values submitted by the user, if any.
158 This array is passed to hook_user op login.
159 @return boolean
160 True if the login succeeds, False otherwise.
161 """
162 form = lib_common.drupal_get_form('user_login')
163 state['values'] = edit
164 if (php.empty(state['values']['name'])):
165 state['values']['name'] = account.name
166
167 lib_plugin.plugins['user'].login_name_validate(
168 form, state, php.array_(account))
169 if (lib_form.get_errors()):
170
171 return False
172
173 lib_bootstrap.user = account
174 lib_plugin.plugins['user'].authenticate_finalize(state['values'])
175 return True
176
177
178
179 -def load(array_={}):
180 """
181 Fetch a user object.
182
183 @param array
184 An associative array of attributes to search for in selecting the
185 user, such as user name or e-mail address.
186
187 @return
188 A fully-loaded user object upon successful user load or False if user
189 cannot be loaded.
190 """
191
192 query = []
193 params = []
194 if (php.is_numeric(array_)):
195 array_ = {'uid' : array}
196 elif (not php.is_array(array_)):
197 return False
198 for key,value in array_.items():
199 if (key == 'uid' or key == 'status'):
200 query.append( key + " = %d" )
201 params.append( value )
202 elif (key == 'pass'):
203 query.append( "pass = '%s'" )
204 params.append( value )
205 else:
206 query.append( "LOWER(key) = LOWER('%s')" )
207 params.append( value )
208 result = lib_database.query('SELECT * FROM {users} u WHERE ' + \
209 php.implode(' AND ', query), params)
210 this_user = lib_database.fetch_object(result)
211 if (this_user):
212 this_user = lib_bootstrap.drupal_unpack(this_user)
213 this_user.roles = {}
214 if (this_user.uid):
215 this_user.roles[lib_bootstrap.DRUPAL_AUTHENTICATED_RID] = \
216 'authenticated user'
217 else:
218 this_user.roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user'
219 result = lib_database.query(\
220 'SELECT r.rid, r.name FROM {role} r ' + \
221 'INNER JOIN {users_roles} ur ON ur.rid = r.rid ' + \
222 'WHERE ur.uid = %d', this_user.uid)
223 while True:
224 role = lib_database.fetch_object(result)
225 if not role:
226 break
227 this_user.roles[role.rid] = role.name
228 plugin_invoke('load', array_, this_user)
229 else:
230 this_user = False
231
232 if hasattr(this_user, 'pass'):
233 setattr(this_user, 'pass_', getattr(this_user, 'pass'))
234 return this_user
235
236
237 -def save(account, array_={}, category = 'account'):
238 """
239 Save changes to a user account or add a new user.
240
241 @param account
242 The user object for the user to modify or add. If user.uid is
243 omitted, a new user will be added.
244
245 @param array
246 An array of fields and values to save. For example array('name'
247 : 'My name'). Keys that do not belong to columns in the user-related
248 tables are added to the a serialized array in the 'data' column
249 and will be loaded in the user.data array by user_load().
250 Setting a field to None deletes it from the data column.
251
252 @param category
253 (optional) The category for storing profile information in.
254
255 @return
256 A fully-loaded user object upon successful save or False
257 if the save failed.
258 """
259 table = lib_common.get_schema('users')
260 user_fields = table['fields']
261 if (not php.empty(array_['pass'])):
262
263 array_['pass'] = hash_password(php.trim(array_['pass']))
264
265 if (not array_['pass']):
266 return False
267 else:
268
269 del(array_['pass'])
270 if (php.is_object(account) and account.uid > 0):
271 plugin_invoke('update', array_, account, category)
272 data = php.unserialize(lib_database.result(lib_database.query(\
273 'SELECT data FROM {users} WHERE uid = %d', account.uid)))
274
275
276 if (php.empty(array_['access']) and php.empty(account.access) and \
277 lib_plugin.plugins['user'].access('administer users')):
278 array_['access'] = php.time_()
279 for key,value in array_.items():
280
281
282 if (key != 'roles' and ph.empty(user_fields[key])):
283 if (value is None):
284 del(data[key])
285 else:
286 data[key] = value
287 array_['data'] = data
288 array_['uid'] = account.uid
289
290 success = lib_common.drupal_write_record('users', array_, 'uid')
291 if (not success):
292
293
294 return False
295
296 if (php.isset(php.array_['roles']) and php.is_array(array_['roles'])):
297 lib_database.db_query('DELETE FROM {users_roles} WHERE uid = %d', \
298 account.uid)
299 for rid in php.array_keys(array_['roles']):
300 if (not php.in_array(rid, (DRUPAL_ANONYMOUS_RID, \
301 DRUPAL_AUTHENTICATED_RID))):
302 lin_database.db_query(\
303 'INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', \
304 account.uid, rid)
305
306 if (php.isset(array_['status']) and array_['status'] == 0):
307 lib_session.destroy_uid(account.uid)
308
309
310 if (not empty(array_['pass'])):
311 lib_session.destroy_uid(account.uid)
312 lib_session.regenerate()
313
314 this_user = load({'uid' : account.uid})
315
316 if (php.isset(array_['status']) and array_['status'] != account.status):
317
318 op = ('status_activated' if (array_['status'] == 1) else \
319 'status_blocked')
320 _mail_notify(op, this_user)
321 plugin_invoke('after_update', array_, this_user, category)
322 else:
323
324 if (not php.isset(array_['created'])):
325 array_['created'] = php.time_()
326
327
328 if (php.empty(array_['access']) and access('administer users')):
329 array_['access'] = php.time_()
330 success = lib_common.drupal_write_record('users', array_)
331 if (not success):
332
333
334 return False
335
336 this_user = load({'uid' : array_['uid']})
337 plugin_invoke('insert', array_, this_user, category)
338
339
340 data = []
341 for key,value in array_.items():
342 if ((key != 'roles') and (php.empty(user_fields[key])) and \
343 (value != None)):
344 data[key] = value
345 if (not empty(data)):
346 data_array = {'uid' : user.uid, 'data' : data}
347 lib_common.drupal_write_record('users', data_array, 'uid')
348
349 if (php.isset(array_['roles']) and php.is_array(array_['roles'])):
350 lib_database.db_query('DELETE FROM {users_roles} WHERE uid = %d', \
351 array_['uid'])
352 for rid in php.array_keys(array_['roles']):
353 if (not php.in_array(rid, (DRUPAL_ANONYMOUS_RID, \
354 DRUPAL_AUTHENTICATED_RID))):
355 db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)', \
356 array_['uid'], rid)
357
358 this_user = load({'uid' : array_['uid']})
359 return this_user
360
361
362
364 """
365 Verify the syntax of the given name.
366 """
367 if (not name):
368 return lib_common.t('You must enter a username.')
369 if (php.substr(name, 0, 1) == ' '):
370 return lib_common.t('The username cannot begin with a space.')
371 if (php.substr(name, -1) == ' '):
372 return lib_common.t('The username cannot end with a space.')
373 if (php.strpos(name, ' ') != False):
374 return lib_common.t(\
375 'The username cannot contain multiple spaces in a row.')
376 if (php.preg_match('/[^\x80-\xF7 a-z0-9@_.\'-]/i', name)):
377 return lib_common.t('The username contains an illegal character.')
378 if (php.preg_match(\
379
380 '/[\x80-\xA0' + \
381
382 '\xAD' + \
383
384 '\u2000-\u200F' + \
385
386 '\u2028-\u202F' + \
387
388 '\u205F-\u206F' + \
389
390 '\uFEFF' + \
391
392 '\uFF01-\uFF60' + \
393
394 '\xFFF9-\xFFFD' + \
395
396 '\x00-\x1F]/u', \
397 name)):
398 return lib_common.t('The username contains an illegal character.')
399 if (drupal_strlen(name) > USERNAME_MAX_LENGTH):
400 return lib_common.t(\
401 'The username %name is too long: it must be %max characters or less.', \
402 {'%name' : name, '%max' : USERNAME_MAX_LENGTH})
403
404
405
407 if (not mail):
408 return lib_common.t('You must enter an e-mail address.')
409 if (not valid_email_address(mail)):
410 return lib_common.t('The e-mail address %mail is not valid.', \
411 {'%mail' : mail})
412
413
414
416 php.Reference.check(form)
417 php.Reference.check(form_state)
418
419 validators = {
420 'file_validate_is_image' : [],
421 'file_validate_image_resolution' : \
422 (lib_bootstrap.variable_get('user_picture_dimensions', '85x85')),
423 'file_validate_size' : \
424 (lib_bootstrap.variable_get('user_picture_file_size', '30') * 1024)
425 }
426 file_ = lib_file.save_upload('picture_upload', validators)
427 if (file_):
428
429 if (php.isset(form_state['values']['_account'].picture) and \
430 lib_file.exists(form_state['values']['_account'].picture)):
431 lib_file.delete(form_state['values']['_account'].picture)
432
433
434
435 info = image_get_info(file_.filepath)
436 destination = lib_bootstrap.variable_get('user_picture_path', \
437 'pictures') + '/picture-' + form['#uid'] + '.' + info['extension']
438 if (lib_file.copy(file_, destination, FILE_EXISTS_REPLACE)):
439 form_state['values']['picture'] = file_.filepath
440 else:
441 lib_form.set_error('picture_upload', \
442 lib_common.t("Failed to upload the picture image; " + \
443 "the %directory directory doesn't exist or is not writable.", \
444 {'%directory' : \
445 lib_common.variable_get('user_picture_path', 'pictures')}))
446
447
449 """
450 Generate a random alphanumeric password.
451 """
452
453
454
455
456 allowable_characters = \
457 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'
458
459 len_ = php.strlen(allowable_characters) - 1
460
461 pass_ = ''
462
463 for i in range(length):
464
465
466 pass_ += allowable_characters[php.mt_rand(0, len_)]
467 return pass_
468
469
471 """
472 Determine the permissions for one or more roles.
473
474 @param roles
475 An array whose keys are the role IDs of interest, such as user.roles.
476 @param reset
477 Optional parameter - if True data in the static variable is rebuilt.
478
479 @return
480 An array indexed by role ID. Each value is an array whose keys are the
481 permission strings for the given role ID.
482 """
483 php.static(role_permissions, 'stored_permissions', {})
484 if (reset):
485
486 role_permissions.stored_permissions = {}
487 role_permissions_ = fetch = []
488 if (roles):
489 for rid,name in roles.items():
490 if (php.isset(role_permissions.stored_permissions[rid])):
491 role_permissions_[rid] = role_permissions.stored_permissions[rid]
492 else:
493
494 fetch.append( rid )
495
496 role_permissions.stored_permissions[rid] = {}
497 if (fetch):
498
499
500 result = lib_database.query(\
501 "SELECT r.rid, p.permission FROM {role} r " + \
502 "INNER JOIN {role_permission} p ON p.rid = r.rid " + \
503 "WHERE r.rid IN (" + lib_database.placeholders(fetch) + ")", fetch)
504 while True:
505 row = lib_database.fetch_array(result)
506 if not row:
507 break
508 role_permissions.stored_permissions[row['rid']][row['permission']] = \
509 True
510 for rid in fetch:
511
512 role_permissions_[rid] = role_permissions.stored_permissions[rid]
513 return role_permissions_
514
515
516 -def access(string_, account=None, reset=False):
517 """
518 Determine whether the user has a given privilege.
519
520 @param string
521 The permission, such as "administer nodes", being checked for.
522 @param account
523 (optional) The account to check,
524 if not given use currently logged in user.
525 @param reset
526 (optional) Resets the user's permissions cache, which will result in a
527 recalculation of the user's permissions. This is necessary to support
528 dynamically added user roles.
529
530 @return
531 Boolean True if the current user has the requested permission.
532
533 All permission checks in Drupal should go through this function. This
534 way, we guarantee consistent behavior, and ensure that the superuser
535 can perform all actions.
536 """
537 php.static(access, 'perm', {})
538 if (reset):
539 access.perm = {}
540 if (account is None):
541 account = lib_bootstrap.user
542
543 if (account.uid == 1):
544 return True
545
546
547 if (not php.isset(access.perm[account.uid])):
548 role_permissions = role_permissions(account.roles, reset)
549 access.perms = {}
550 for one_role in role_permissions:
551 access.perms += one_role
552 access.perm[account.uid] = access.perms
553 return php.isset(access.perm[account.uid][string])
554
555
557 """
558 Checks for usernames blocked by user administration.
559
560 @return boolean True for blocked users, False for active.
561 """
562 deny = lib_database.fetch_object(\
563 lib_database.query(\
564 "SELECT name FROM {users} WHERE status = 0 AND name = LOWER('%s')", \
565 name))
566 return deny
567
568
570 """
571 Implementation of hook_perm().
572 """
573 return {
574 'administer permissions' : lib_common.t(\
575 'Manage the permissions assigned to user roles + %warning', \
576 {'%warning' : lib_common.t(\
577 'Warning: Give to trusted roles only; ' + \
578 'this permission has security implications.')}),
579 'administer users' : lib_common.t(\
580 'Manage or block users, and manage their role assignments.'),
581 'access user profiles' : lib_common.t(\
582 'View profiles of users on the site, ' + \
583 'which may contain personal information.'),
584 'change own username' : t('Select a different username.'),
585 }
586
587
589 """
590 Implementation of hook_file_download().
591
592 Ensure that user pictures (avatars) are always downloadable.
593 """
594 if (php.strpos(file, lib_bootstrap.variable_get(\
595 'user_picture_path', 'pictures') + '/picture-') == 0):
596 info = lib_plugin.plugins['image'].get_info(\
597 lib_plugin.plugins['file'].create_path(file))
598 return ('Content-type: ' + info['mime_type'],)
599
600
601 -def hook_search(op = 'search', keys = None, skip_access_check = False):
602 """
603 Implementation of hook_search().
604 """
605 if op == 'name':
606 if (skip_access_check or access('access user profiles')):
607 return lib_common.t('Users')
608 elif op == 'search':
609 if (access('access user profiles')):
610 find = []
611
612 keys = php.preg_replace('not \*+not ', '%', keys)
613 if (access('administer users')):
614
615 result = lib_database.pager_query(\
616 "SELECT name, uid, mail FROM {users} " + \
617 "WHERE LOWER(name) LIKE LOWER('%%%s%%') OR " + \
618 "LOWER(mail) LIKE LOWER('%%%s%%')", 15, 0, None, keys, keys)
619 while True:
620 account = db_fetch_object(result)
621 if not account:
622 break
623 find.append({
624 'title' : account.name + ' (' + account.mail + ')', \
625 'link' : \
626 lib_common.url('user/' + account.uid, {'absolute' : True})
627 })
628 else:
629 result = lib_database.pager_query(\
630 "SELECT name, uid FROM {users} " + \
631 "WHERE LOWER(name) LIKE LOWER('%%%s%%')", 15, 0, None, keys)
632 while True:
633 account = db_fetch_object(result)
634 if not account:
635 break;
636 find.append({
637 'title' : account.name,
638 'link' : lib_common.url('user/' + account.uid, \
639 {'absolute' : True})
640 })
641 return find
642
643
644
646 """
647 Implementation of hook_elements().
648 """
649 return {
650 'user_profile_category' : [],
651 'user_profile_item' : []
652 }
653
654
655
656 -def hook_user(type, edit, account, category=None):
657 """
658 Implementation of hook_user().
659 """
660 php.Reference.check(edit)
661 php.Reference.check(account)
662 if (type == 'view'):
663 account.content['user_picture'] = {
664 '#value' : lib_theme.theme('user_picture', account),
665 '#weight' : -10
666 }
667 if (not php.isset(account.content, 'summary')):
668 account.content['summary'] = {}
669 account.content['summary'] += {
670 '#type' : 'user_profile_category',
671 '#attributes' : {'class' : 'user-member'},
672 '#weight' : 5,
673 '#title' : lib_common.t('History')
674 }
675 account.content['summary']['member_for'] = {
676 '#type' : 'user_profile_item',
677 '#title' : lib_theme.t('Member for'),
678 '#markup' : format_interval(php.time_() - account.created)
679 }
680 if (type == 'form' and category == 'account'):
681 form_state = {}
682 return edit_form(form_state, lib_common.arg(1), edit)
683 if (type == 'validate' and category == 'account'):
684 return _user_edit_validate(arg(1), edit)
685 if (type == 'submit' and category == 'account'):
686 return _user_edit_submit(arg(1), edit)
687 if (type == 'categories'):
688 return ({
689 'name' : 'account',
690 'title' : lib_common.t('Account settings'),
691 'weight' : 1
692 },)
693
694
695
696
697
699 form = {
700 '#action' : lib_common.url(php.GET['q'], \
701 {'query' : drupal_get_destination()}),
702 '#id' : 'user-login-form',
703 '#validate' : login_default_validators(),
704 '#submit' : ('user_login_submit',),
705 }
706 form['name'] = {
707 '#type' : 'textfield',
708 '#title' : t('Username'),
709 '#maxlength' : USERNAME_MAX_LENGTH,
710 '#size' : 15,
711 '#required' : True,
712 }
713 form['pass'] = {
714 '#type' : 'password',
715 '#title' : lib_common.t('Password'),
716 '#maxlength' : 60,
717 '#size' : 15,
718 '#required' : True
719 }
720 form['submit'] = {
721 '#type' : 'submit',
722 '#value' : lib_common.t('Log in')
723 }
724 items = {}
725 if (lib_bootstrap.variable_get('user_register', 1)):
726 items.append( lib_common.l(\
727 lib_common.t('Create new account'), 'user/register', \
728 {'attributes' : {'title' : t('Create a new user account.')}}) )
729 items.append( lib_common.l(\
730 t('Request new password'), \
731 'user/password', {'attributes' : \
732 {'title' : lib_common.t('Request new password via e-mail.')}}) )
733 form['links'] = {'#markup' : lib_theme.theme('item_list', items)}
734 return form
735
736
737
738
740 """
741 Implementation of hook_block().
742 """
743 if (op == 'list'):
744 blocks = {
745 'login' : {},
746 'navigation' : {},
747 'new' : {},
748 'online' : {}
749 }
750 blocks['login']['info'] = lib_common.t('User login')
751
752 blocks['login']['cache'] = BLOCK_NO_CACHE
753 blocks['navigation']['info'] = lib_common.t('Navigation')
754
755
756 blocks['navigation']['cache'] = BLOCK_NO_CACHE
757 blocks['new']['info'] = lib_common.t('Who\'s new')
758
759 blocks['online']['info'] = lib_common.t('Who\'s online')
760 blocks['online']['cache'] = BLOCK_NO_CACHE
761 return blocks
762 elif (op == 'configure' and delta == 'new'):
763 form['user_block_whois_new_count'] = {
764 '#type' : 'select',
765 '#title' : lib_common.t('Number of users to display'),
766 '#default_value' : \
767 lib_bootstrap.variable_get('user_block_whois_new_count', 5),
768 '#options' : drupal_map_assoc((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
769 }
770 return form
771 elif (op == 'configure' and delta == 'online'):
772 period = drupal_map_assoc(
773 (30, 60, 120, 180, 300, 600, 900, 1800, 2700, 3600, 5400, 7200, \
774 10800, 21600, 43200, 86400), 'format_interval')
775 form['user_block_seconds_online'] = {
776 '#type' : 'select',
777 '#title' : lib_common.t('User activity'),
778 '#default_value' : \
779 lib_bootstrap.variable_get('user_block_seconds_online', 900),
780 '#options' : period,
781 '#description' : \
782 lib.common.t('A user is considered online for ' + \
783 'this long after they have last viewed a page.')
784 }
785 form['user_block_max_list_count'] = {'#type' : 'select', \
786 '#title' : lib_common.t('User list length'), \
787 '#default_value' : \
788 lib_bootstrap.variable_get('user_block_max_list_count', 10), \
789 '#options' : drupal_map_assoc(\
790 (0, 5, 10, 15, 20, 25, 30, 40, 50, 75, 100)), \
791 '#description' : lib_common.t('Maximum number of ' + \
792 'currently online users to display.')}
793 return form
794 elif (op == 'save' and delta == 'new'):
795 lib_bootstrap.variable_set('user_block_whois_new_count', \
796 edit['user_block_whois_new_count'])
797 elif (op == 'save' and delta == 'online'):
798 lib_bootstrap.variable_set('user_block_seconds_online', \
799 edit['user_block_seconds_online'])
800 lib_bootstrap.variable_set('user_block_max_list_count', \
801 edit['user_block_max_list_count'])
802 elif (op == 'view'):
803 block = {}
804 if delta == 'login':
805
806 if (lib_bootstrap.user.uid < 1 and not \
807 (lib_path.arg(0) == 'user' and not php.is_numeric(lib_path.arg(1)))):
808 block['subject'] = lib_common.t('User login')
809 block['content'] = drupal_get_form('user_login_block')
810 return block
811 elif delta == 'navigation':
812 menu = lib_menu.tree()
813 if (menu):
814 block['subject'] = (check_plain(lib_bootstrap.user.name) if \
815 (user.uid > 0) else \
816 lib_common.t('Navigation'))
817 block['content'] = menu
818 return block
819 elif delta == 'new':
820 if (access('access content')):
821
822
823 result = lib_database.query_range(\
824 'SELECT uid, name FROM {users} ' + \
825 'WHERE status != 0 AND access != 0 ' + \
826 'ORDER BY created DESC', 0, \
827 lib_common.variable_get('user_block_whois_new_count', 5))
828 while True:
829 account = lib_database.fetch_object(result)
830 if not account:
831 break
832 items.append( account )
833 output = lib_theme.theme('user_list', items)
834 block['subject'] = lib_common.t('Who\'s new')
835 block['content'] = output
836 return block
837 elif delta == 'online':
838 if (access('access content')):
839
840 interval = time() - variable_get('user_block_seconds_online', 900)
841
842
843
844 anonymous_count = sess_count(interval)
845 authenticated_users = lib_database.query(\
846 'SELECT DISTINCT u.uid, u.name, s.timestamp ' + \
847 'FROM {users} u ' + \
848 'INNER JOIN {sessions} s ON u.uid = s.uid ' + \
849 'WHERE s.timestamp >= %d AND s.uid > 0 ' + \
850 'ORDER BY s.timestamp DESC', interval)
851 authenticated_count = 0
852 max_users = lib_bootstrap.variable_get('user_block_max_list_count', 10)
853 items = []
854 while True:
855 account = lib_database.fetch_object(authenticated_users)
856 if (max_users > 0):
857 items.append( account )
858 max_users -= 1
859 authenticated_count += 1
860
861 if (anonymous_count == 1 and authenticated_count == 1):
862 output = lib_common.t(\
863 'There is currently %members and %visitors online.', \
864 {'%members' : \
865 format_plural(authenticated_count, '1 user', '@count users'), \
866 '%visitors' : format_plural(anonymous_count, '1 guest', \
867 '@count guests')})
868 else:
869 output = lib_common.t(\
870 'There are currently %members and %visitors online.', \
871 {'%members' : format_plural(authenticated_count, '1 user', \
872 '@count users'), '%visitors' : \
873 format_plural(anonymous_count, '1 guest', '@count guests')})
874
875 max_users = lib_bootstrap.variable_get('user_block_max_list_count', 10)
876 if (authenticated_count and max_users):
877 output += lib_theme.theme('user_list', items, \
878 lib_common.t('Online users'))
879 block['subject'] = lib_common.t('Who\'s online')
880 block['content'] = output
881 return block
882
883
884
886 """
887 Process variables for user-picture.tpl.php.
888
889 The variables array contains the following arguments:
890 - account
891
892 @see user-picture.tpl.php
893 """
894 php.Reference.check(variables)
895 variables['picture'] = ''
896 if (lib_bootstrap.variable_get('user_pictures', 0)):
897 account = variables['account']
898 if (not php.empty(account.picture) and php.file_exists(account.picture)):
899 picture = lib_file.create_url(account.picture)
900 elif (lib_bootstrap.variable_get('user_picture_default', '')):
901 picture = variable_get('user_picture_default', '')
902 if (php.isset(picture)):
903 alt = lib_common.t("@user's picture", {'@user' : \
904 (account.name if account.name else \
905 lib_bootstrap.variable_get('anonymous', t('Anonymous')))})
906 variables['picture'] = theme('image', picture, alt, alt, '', False)
907 if (not empty(account.uid) and access('access user profiles')):
908 attributes = {'attributes' : {'title' : t('View user profile.')}, \
909 'html' : True}
910 variables['picture'] = lib_common.l(variables['picture'], \
911 "user/account.uid", attributes)
912
913
914
915
917 """
918 Make a list of users.
919
920 @param users
921 An array with user objects. Should contain at least the name and uid.
922 @param title
923 (optional) Title to pass on to theme_item_list().
924
925 @ingroup themeable
926 """
927 if (not php.empty(users)):
928 for user in users:
929 items.append( lib_theme.theme('username', user) )
930 return lib_theme.theme('item_list', items, title)
931
932
933
934
938
939
941 return bool(lib_bootstrap.user.uid)
942
943
946
947
948
950 return account and account.uid and \
951 (\
952
953 (lib_bootstrap.user.uid == account.uid) or \
954
955 access('administer users') or \
956
957 (account.access and account.status and access('access user profiles')) \
958 )
959
960
961 """
962 Access callback for user account editing.
963 """
965 return ((lib_bootstrap.user.uid == account.uid) or \
966 access('administer users')) and account.uid > 0
967
968
970 arg_[1] = load(lib_bootstrap.user.uid)
971 return arg_
972
973
975 """
976 Implementation of hook_menu().
977 """
978 items = {}
979 items['user/autocomplete'] = {
980 'title' : 'User autocomplete',
981 'page callback' : 'user_autocomplete',
982 'access callback' : 'user_access',
983 'access arguments' : ('access user profiles',),
984 'type' : MENU_CALLBACK
985 }
986
987 items['user'] = {
988 'title' : 'User account',
989 'page callback' : 'user_page',
990 'access callback' : True,
991 'type' : MENU_CALLBACK
992 }
993 items['user/login'] = {
994 'title' : 'Log in',
995 'access callback' : 'user_is_anonymous',
996 'type' : MENU_DEFAULT_LOCAL_TASK
997 }
998 items['user/register'] = {
999 'title' : 'Create new account',
1000 'page callback' : 'drupal_get_form',
1001 'page arguments' : ('user_register',),
1002 'access callback' : 'user_register_access',
1003 'type' : MENU_LOCAL_TASK
1004 }
1005 items['user/password'] = {
1006 'title' : 'Request new password',
1007 'page callback' : 'drupal_get_form',
1008 'page arguments' : ('user_pass',),
1009 'access callback' : 'user_is_anonymous',
1010 'type' : MENU_LOCAL_TASK
1011 }
1012 items['user/reset/%/%/%'] = {
1013 'title' : 'Reset password',
1014 'page callback' : 'drupal_get_form',
1015 'page arguments' : ('user_pass_reset', 2, 3, 4),
1016 'access callback' : True,
1017 'type' : MENU_CALLBACK
1018 }
1019
1020 items['admin/user'] = {
1021 'title' : 'User management',
1022 'description' : \
1023 "Manage your site's users, groups and access to site features.",
1024 'position' : 'left',
1025 'page callback' : 'system_admin_menu_block_page',
1026 'access arguments' : ('access administration pages',)
1027 }
1028 items['admin/user/user'] = {
1029 'title' : 'Users',
1030 'description' : 'List, add, and edit users.',
1031 'page callback' : 'user_admin',
1032 'page arguments' : ('list',),
1033 'access arguments' : ('administer users',),
1034 }
1035 items['admin/user/user/list'] = {
1036 'title' : 'List',
1037 'type' : MENU_DEFAULT_LOCAL_TASK,
1038 'weight' : -10
1039 }
1040 items['admin/user/user/create'] = {
1041 'title' : 'Add user',
1042 'page arguments' : ('create',),
1043 'access arguments' : ('administer users',),
1044 'type' : MENU_LOCAL_TASK
1045 }
1046 items['admin/user/settings'] = {
1047 'title' : 'User settings',
1048 'description' : \
1049 'Configure default behavior of users, including registration ' + \
1050 'requirements, e-mails, and user pictures.',
1051 'page callback' : 'drupal_get_form',
1052 'page arguments' : ('user_admin_settings',),
1053 'access arguments' : ('administer users',)
1054 }
1055
1056 items['admin/user/permissions'] = {
1057 'title' : 'Permissions',
1058 'description' : 'Determine access to features by ' + \
1059 'selecting permissions for roles.',
1060 'page callback' : 'drupal_get_form',
1061 'page arguments' : ('user_admin_perm',),
1062 'access arguments' : ('administer permissions',)
1063 }
1064 items['admin/user/roles'] = {
1065 'title' : 'Roles',
1066 'description' : 'List, edit, or add user roles.',
1067 'page callback' : 'drupal_get_form',
1068 'page arguments' : ('user_admin_new_role',),
1069 'access arguments' : ('administer permissions',)
1070 }
1071 items['admin/user/roles/edit'] = {
1072 'title' : 'Edit role',
1073 'page arguments' : ('user_admin_role',),
1074 'access arguments' : ('administer permissions',),
1075 'type' : MENU_CALLBACK
1076 }
1077 items['logout'] = {
1078 'title' : 'Log out',
1079 'access callback' : 'user_is_logged_in',
1080 'page callback' : 'user_logout',
1081 'weight' : 10
1082 }
1083 items['user/%user_uid_optional'] = {
1084 'title' : 'My account',
1085 'title callback' : 'user_page_title',
1086 'title arguments' : (1,),
1087 'page callback' : 'user_view',
1088 'page arguments' : (1,),
1089 'access callback' : 'user_view_access',
1090 'access arguments' : (1,),
1091 'parent' : ''
1092 }
1093 items['user/%user/view'] = {
1094 'title' : 'View',
1095 'type' : MENU_DEFAULT_LOCAL_TASK,
1096 'weight' : -10
1097 }
1098 items['user/%user/delete'] = {
1099 'title' : 'Delete',
1100 'page callback' : 'drupal_get_form',
1101 'page arguments' : ('user_confirm_delete', 1),
1102 'access callback' : 'user_access',
1103 'access arguments' : ('administer users',),
1104 'type' : MENU_CALLBACK
1105 }
1106 items['user/%user_category/edit'] = {
1107 'title' : 'Edit',
1108 'page callback' : 'user_edit',
1109 'page arguments' : (1,),
1110 'access callback' : 'user_edit_access',
1111 'access arguments' : (1,),
1112 'type' : MENU_LOCAL_TASK,
1113 'load arguments' : ('%map', '%index')
1114 }
1115 items['user/%user_category/edit/account'] = {
1116 'title' : 'Account',
1117 'type' : MENU_DEFAULT_LOCAL_TASK,
1118 'load arguments' : ('%map', '%index')
1119 }
1120 empty_account = php.stdClass()
1121 categories = _user_categories(empty_account)
1122 if (categories and (php.count(categories) > 1)):
1123 for key,category in categories.items():
1124
1125 if (category['name'] != 'account'):
1126 items['user/%user_category/edit/' + category['name']] = {
1127 'title callback' : 'check_plain',
1128 'title arguments' : (category['title'],),
1129 'page callback' : 'user_edit',
1130 'page arguments' : (1, 3),
1131 'access callback' : (category['access callback'] if \
1132 php.isset(category['access callback']) else 'user_edit_access'),
1133 'access arguments' : (category['access arguments'] if \
1134 php.isset(category['access arguments']) else (1,)),
1135 'type' : MENU_LOCAL_TASK,
1136 'weight' : category['weight'],
1137 'load arguments' : ('%map', '%index'),
1138 'tab_parent' : 'user/%/edit'
1139 }
1140 return items
1141
1142
1143
1147
1148
1149
1151 return load((arg_ if php.isset(arg_) else lib_bootstrap.user.uid))
1152
1153
1154
1156 """
1157 Return a user object after checking if any profile category in
1158 the path exists.
1159 """
1160 php.static(category_load, 'user_categories')
1161 php.static(category_load, 'accounts')
1162 php.Reference.check(map_)
1163
1164 if (not php.isset(category_load.accounts[uid])):
1165 category_load.accounts[uid] = load(uid)
1166 valid = True
1167 account = category_load.accounts[uid]
1168 if account:
1169
1170
1171 category_index = index + 2
1172
1173 category_path = php.implode('/', php.array_slice(map_, category_index))
1174 if (category_path):
1175
1176 valid = False
1177 if (not php.isset(category_load.user_categories)):
1178 empty_account = php.stdClass()
1179 category_load.user_categories = _categories(empty_account)
1180 for category in category_load.user_categories:
1181 if (category['name'] == category_path):
1182 valid = True
1183
1184 map_ = php.array_slice(map_, 0, category_index)
1185
1186 map_[category_index] = category_path
1187 break
1188 return (account if valid else False)
1189
1190
1191
1193 """
1194 Returns the user id of the currently logged in user.
1195 """
1196
1197
1198
1199 return (lib_bootstrap.user.uid if (php.empty(arg_) or arg_ == '%') else arg_)
1200
1201
1202
1203 -def page_title(account):
1204 """
1205 Menu item title callback - use the user name if it's not the current user.
1206 """
1207 if (account.uid == lib_bootstrap.user.uid):
1208 return lib_common.t('My account')
1209 return account.name
1210
1211
1212
1214 """
1215 Discover which external authentication module(s) authenticated a username.
1216
1217 @param authname
1218 A username used by an external authentication module.
1219 @return
1220 An associative array with module as key and username as value.
1221 """
1222 result = lib_database.query(\
1223 "SELECT authname, module FROM {authmap} WHERE authname = '%s'", authname)
1224 authmaps = []
1225 has_rows = False
1226 while True:
1227 authmap = lib_database.fetch_object(result)
1228 if not authmap:
1229 break
1230 authmaps[authmap.module] = authmap.authname
1231 has_rows = True
1232 return (authmaps if has_rows else 0)
1233
1234
1235
1237 """
1238 Save mappings of which external authentication module(s) authenticated
1239 a user. Maps external usernames to user ids in the users table.
1240
1241 @param account
1242 A user object.
1243 @param authmaps
1244 An associative array with a compound key and the username as the value.
1245 The key is made up of 'authname_' plus the name of the
1246 external authentication
1247 module.
1248 @see user_external_login_register()
1249 """
1250 for key,value in authmaps.items():
1251 module = explode('_', key, 2)
1252 if (value):
1253 lib_database.query(\
1254 "UPDATE {authmap} SET authname = '%s' " + \
1255 "WHERE uid = %d AND module = '%s'", value, account.uid, module[1])
1256 if (not lib_database.affected_rows()):
1257 lib_database.query(\
1258 "INSERT INTO {authmap} (authname, uid, module) " + \
1259 "VALUES ('%s', %d, '%s')", value, account.uid, module[1])
1260 else:
1261 lib_database.query(\
1262 "DELETE FROM {authmap} WHERE uid = %d AND module = '%s'", \
1263 account.uid, module[1])
1264
1265
1266
1268 """
1269 Form builder; the main user login form.
1270
1271 @ingroup forms
1272 """
1273 php.Reference.check(form_state)
1274
1275 if (lib_bootstrap.user.uid):
1276 drupal_goto('user/' + lib_bootstrap.user.uid)
1277
1278 form['name'] = {
1279 '#type' : 'textfield',
1280 '#title' : lib_common.t('Username'),
1281 '#size' : 60,
1282 '#maxlength' : USERNAME_MAX_LENGTH,
1283 '#required' : True,
1284 '#attributes' : {'tabindex' : '1'}
1285 }
1286 form['name']['#description'] = lib_common.t('Enter your @s username.', \
1287 {'@s' : lib_bootstrap.variable_get('site_name', 'Drupal')})
1288 form['pass'] = {
1289 '#type' : 'password',
1290 '#title' : lib_common.t('Password'),
1291 '#description' : lib_common.t(\
1292 'Enter the password that accompanies your username.'),
1293 '#required' : True,
1294 '#attributes' : {'tabindex' : '2'}
1295 }
1296 form['#validate'] = login_default_validators()
1297 form['submit'] = {'#type' : 'submit', '#value' : lib_common.t('Log in'), \
1298 '#weight' : 2, '#attributes' : {'tabindex' : '3'}}
1299 return form
1300
1301
1302
1304 """
1305 Set up a series for validators which check for blocked users,
1306 then authenticate against local database, then return an error if
1307 authentication fails. Distributed authentication modules are welcome
1308 to use hook_form_alter() to change this series in order to
1309 authenticate against their user database instead of the local users
1310 table.
1311
1312 We use three validators instead of one since external authentication
1313 modules usually only need to alter the second validator.
1314
1315 @see user_login_name_validate()
1316 @see user_login_authenticate_validate()
1317 @see user_login_final_validate()
1318 @return array
1319 A simple list of validate functions.
1320 """
1321 return ('user_login_name_validate', \
1322 'user_login_authenticate_validate', 'user_login_final_validate')
1323
1324
1325
1327 """
1328 A FAPI validate handler. Sets an error if supplied username
1329 has been blocked.
1330 """
1331 if (php.isset(form_state['values']['name']) and \
1332 is_blocked(form_state['values']['name'])):
1333
1334 form_set_error('name', lib_common.t(\
1335 'The username %name has not been activated or is blocked.', \
1336 {'%name' : form_state['values']['name']}))
1337
1338
1340 """
1341 A validate handler on the login form. Check supplied username/password
1342 against local users table. If successful, sets the global user object.
1343 """
1344 authenticate(form_state['values'])
1345
1346
1347
1349 """
1350 A validate handler on the login form. Should be the last validator. Sets an
1351 error if user has not been authenticated yet.
1352 """
1353 php.Reference.check(form_state)
1354 if (not lib_bootstrap.user.uid):
1355 form_set_error('name', \
1356 lib_common.t(\
1357 'Sorry, unrecognized username or password. ' + \
1358 '<a href="@password">Have you forgotten your password?</a>', \
1359 {'@password' : url('user/password')}))
1360 watchdog('user', 'Login attempt failed for %user.', \
1361 {'%user' : form_state['values']['name']})
1362
1363
1364
1366 """
1367 Try to log in the user locally.
1368
1369 @param form_values
1370 Form values with at least 'name' and 'pass' keys, as well as anything else
1371 which should be passed along to hook_user op 'login'.
1372
1373 @return
1374 A user object, if successful.
1375 """
1376 password = php.trim(form_values['pass'])
1377
1378 if (not php.empty(form_values['name']) and not php.empty(password)):
1379 account = lib_database.fetch_object(\
1380 lib_database.query(\
1381 "SELECT * FROM {users} WHERE name = '%s' AND status = 1", \
1382 form_values['name']))
1383 if (account):
1384
1385 if (check_password(password, account)):
1386 if (needs_new_hash(account)):
1387 new_hash = hash_password(password)
1388 if (new_hash):
1389 lib_database.query(\
1390 "UPDATE {users} SET pass = '%s' WHERE uid = %d", \
1391 new_hash, account.uid)
1392 account = load({'uid' : account.uid, 'status' : 1})
1393 lib_bootstrap.user = account
1394 authenticate_finalize(form_values)
1395 return lib_bootstrap.user
1396
1397
1398
1400 """
1401 Finalize the login process. Must be called when logging in a user.
1402
1403 The function records a watchdog message about the new session, saves the
1404 login timestamp, calls hook_user op 'login' and generates a new session.
1405
1406 param edit
1407 This array is passed to hook_user op login.
1408 """
1409 php.Reference.check(edit)
1410 watchdog('user', 'Session opened for %name.', \
1411 {'%name' : lib_bootstrap.user.name})
1412
1413
1414 lib_bootstrap.user.login = php.time_()
1415 lib_database.query("UPDATE {users} SET login = %d WHERE uid = %d", \
1416 lib_bootstrap.user.login, lib_bootstrap.user.uid)
1417 plugin_invoke('login', edit, lib_bootstrap.user)
1418 lib_session.regenerate()
1419
1420
1421
1422
1434
1435
1436
1438 """
1439 Helper function for authentication modules. Either login in or registers
1440 the current user, based on username. Either way, the global user object is
1441 populated based on name.
1442 """
1443 existing_user = load({'name' : name});
1444 if (php.isset(existing_user.uid)):
1445 lib_bootstrap.user = existing_user;
1446 else:
1447
1448 userinfo = {
1449 'name' : name,
1450 'pass' : password(),
1451 'init' : name,
1452 'status' : 1,
1453 'access' : php.time_()
1454 }
1455 account = save('', userinfo)
1456
1457 if (not account):
1458 drupal_set_message(lib_common.t("Error saving user account."), 'error')
1459 return
1460 user_set_authmaps(account, {"authname_module" : name})
1461 user = account
1462 watchdog('user', 'New external user: %name using module %module.', \
1463 {'%name' : name, '%module' : module}, \
1464 WATCHDOG_NOTICE, lib_common.l(lib_common.t('edit'), \
1465 'user/' + lib_bootstrap.user.uid + '/edit'))
1466
1467
1468
1469
1471 timestamp = php.time_()
1472 return url("user/reset/account.uid/timestamp/" + \
1473 pass_rehash(account.pass_, timestamp, account.login), {'absolute' : True})
1474
1475
1476
1478 return php.md5(timestamp + password + login)
1479
1480
1601
1602
1603
1605 php.Reference.check(edit)
1606 user_ = load({'uid' : uid})
1607
1608 if (access('change own username') or access('administer users') or \
1609 not user_.uid):
1610 error = validate_name(edit['name'])
1611 if error:
1612 lib_form.set_error('name', error)
1613 elif (lib_database.result(\
1614 lib_database.query(\
1615 "SELECT COUNT(*) FROM {users} " + \
1616 "WHERE uid != %d AND LOWER(name) = LOWER('%s')", uid, \
1617 edit['name'])) > 0):
1618 lib_form.set_error('name', \
1619 lib_common.t('The name %name is already taken.', \
1620 {'%name' : edit['name']}))
1621
1622 error = validate_mail(edit['mail'])
1623 if error:
1624 lib_form.set_error('mail', error)
1625 elif (lib_database.result(lib_database.query(\
1626 "SELECT COUNT(*) FROM {users} " + \
1627 "WHERE uid != %d AND LOWER(mail) = LOWER('%s')", uid, \
1628 edit['mail'])) > 0):
1629 lib_form.set_error('mail', \
1630 lib_common.t('The e-mail address %email is already registered. ' + \
1631 '<a href="@password">Have you forgotten your password?</a>', \
1632 {'%email' : edit['mail'], '@password' : url('user/password')}))
1633
1634
1635
1636
1638 php.Reference.check(edit)
1639 user_ = load({'uid' : uid})
1640
1641 if (not php.empty(edit['picture_delete'])):
1642 if (user_.picture and lib_file.exists(user_.picture)):
1643 lib_file.delete(user_.picture)
1644 edit['picture'] = ''
1645 if (php.isset(edit['roles'])):
1646 edit['roles'] = php.array_filter(edit['roles'])
1647
1648
1649
1651 """
1652 Delete a user.
1653
1654 @param edit An array of submitted form values.
1655 @param uid The user ID of the user to delete.
1656 """
1657 account = load({'uid' : uid})
1658 lib_session.destroy_uid(uid)
1659 _mail_notify('status_deleted', account)
1660 lib_plugin.invoke_all('user', 'delete', edit, account)
1661 lib_database.query('DELETE FROM {users} WHERE uid = %d', uid)
1662 lib_database.query('DELETE FROM {users_roles} WHERE uid = %d', uid)
1663 lib_database.query('DELETE FROM {authmap} WHERE uid = %d', uid)
1664 variables = {'%name' : account.name, '%email' : '<' + account.mail + '>'}
1665 watchdog('user', 'Deleted user: %name %email.', variables, WATCHDOG_NOTICE)
1666 lib_plugin.invoke_all('user', 'delete', edit, account)
1667
1668
1669
1670 -def build_content(account):
1671 """
1672 Builds a structured array representing the profile content.
1673
1674 @param account
1675 A user object.
1676
1677 @return
1678 A structured array containing the individual elements of the profile.
1679 """
1680 php.Reference.check(account)
1681 edit = None
1682 plugin_invoke('view', edit, account)
1683
1684 drupal_alter('profile', account)
1685 return account.content
1686
1687
1688
1698
1699
1700 -def _mail_text(key, language=None, variables=[]):
1701 """
1702 Returns a mail string for a variable name.
1703
1704 Used by user_mail() and the settings forms to retrieve strings.
1705 """
1706 langcode = (language.language if php.isset(language) else None)
1707 admin_setting = lib_bootstrap.variable_get('user_mail_' + key, False)
1708 if admin_setting:
1709
1710 return php.strtr(admin_setting, variables)
1711 else:
1712
1713 if key == 'register_no_approval_required_subject':
1714 return t('Account details for not username at not site', \
1715 variables, langcode)
1716 elif key == 'register_no_approval_required_body':
1717 return lib_common.t("not username,\n\nThank you for " + \
1718 "registering at not site. " + \
1719 "You may now log in to not login_uri using the following " + \
1720 "username and password:\n\nusername: not username\npassword: " + \
1721 "not password\n\nYou may also log in by clicking on " + \
1722 "this link or copying and pasting it in your browser:\n\nnot " + \
1723 "login_url\n\nThis is a one-time login, so it can be used " + \
1724 "only once.\n\nAfter logging in, you will be redirected to " + \
1725 "not edit_uri so you can change your password.\n\n\n-- " + \
1726 "not site team", variables, langcode)
1727 elif key == 'register_admin_created_subject':
1728 return lib_common.t('An administrator created an account ' + \
1729 'for you at not site', variables, langcode)
1730 elif key == 'register_admin_created_body':
1731 return lib_common.t("not username,\n\nA site administrator at " + \
1732 "not site has created an account for you. You may now log " + \
1733 "in to not login_uri using the following username " + \
1734 "and password:\n\nusername: not username\npassword: " + \
1735 "not password\n\nYou may also log in by clicking on this " + \
1736 "link or copying and pasting it in your browser:\n\nnot " + \
1737 "login_url\n\nThis is a one-time login, so it can be " + \
1738 "used only once.\n\nAfter logging in, you will be redirected to " + \
1739 "not edit_uri so you can change your password.\n\n\n-- " + \
1740 "not site team", variables, langcode)
1741 elif \
1742 key == 'register_pending_approval_subject' or \
1743 key == 'register_pending_approval_admin_subject':
1744 return lib_common.t('Account details for not username at not ' + \
1745 'site (pending admin approval)', variables, langcode)
1746 elif key == 'register_pending_approval_body':
1747 return lib_common.t("not username,\n\nThank you for registering at " + \
1748 "!site + Your application for an account is currently pending " + \
1749 "approval. Once it has been approved, you will receive " + \
1750 "another e-mail containing information about how to log in, " + \
1751 "set your password, and other " + \
1752 "details.\n\n\n-- not site team", variables, langcode)
1753 elif key == 'register_pending_approval_admin_body':
1754 return lib_common.t("not username has applied for an " + \
1755 "account.\n\nnot edit_uri", variables, langcode)
1756 elif key == 'password_reset_subject':
1757 return lib_common.t('Replacement login information for ' + \
1758 'not username at not site', variables, langcode)
1759 elif key == 'password_reset_body':
1760 return lib_common.t("not username,\n\nA request to reset the " + \
1761 "password for your account has been made at not site.\n\nYou may " + \
1762 "now log in to not uri_brief by clicking on this link or copying " + \
1763 "and pasting it in your browser:\n\nnot login_url\n\nThis " + \
1764 "is a one-time login, so it can be used only once. " + \
1765 "It expires after one day and nothing will happen if it's not " + \
1766 "used.\n\nAfter logging in, you will be redirected to !edit_uri " + \
1767 "so you can change your password.", variables, langcode)
1768 elif key == 'status_activated_subject':
1769 return lib_common.t('Account details for not username at !site ' + \
1770 '(approved)', variables, langcode)
1771 elif key == 'status_activated_body':
1772 return lib_common.t("not username,\n\nYour account at !site " + \
1773 "has been activated.\n\nYou may now log in by clicking on this " + \
1774 "link or copying and pasting it in your browser:\n\n" + \
1775 "!login_url\n\nThis is a one-time login, so it can be used only " + \
1776 "once.\n\nAfter logging in, you will be redirected to " + \
1777 "!edit_uri so you can change your password.\n\nOnce you " + \
1778 "have set your own password, you will be able to log in to " + \
1779 "!login_uri in the future using:\n\nusername: not username\n", \
1780 variables, langcode)
1781 elif key == 'status_blocked_subject':
1782 return lib_common.t('Account details for not username at ' + \
1783 '!site (blocked)', variables, langcode)
1784 elif key == 'status_blocked_body':
1785 return lib_common.t("not username,\n\nYour account on !site has " + \
1786 "been blocked.", variables, langcode)
1787 elif key == 'status_deleted_subject':
1788 return lib_common.t('Account details for not username at ' + \
1789 '!site (deleted)', variables, langcode)
1790 elif key == 'status_deleted_body':
1791 return lib_common.t("not username,\n\nYour account on not " + \
1792 "site has been deleted.", variables, langcode)
1793
1794
1795
1796 -def roles(membersonly=False, permission=None):
1797 """
1798 Retrieve an array of roles matching specified conditions.
1799
1800 @param membersonly
1801 Set this to True to exclude the 'anonymous' role.
1802 @param permission
1803 A string containing a permission. If set, only roles containing that
1804 permission are returned.
1805
1806 @return
1807 An associative array with the role id as the key and the role name as
1808 value.
1809 """
1810
1811 roles_ = {
1812 DRUPAL_ANONYMOUS_RID : None,
1813 DRUPAL_AUTHENTICATED_RID : None
1814 }
1815 if (not php.empty(permission)):
1816 result = lib_database.query(\
1817 "SELECT r.* FROM {role} r " + \
1818 "INNER JOIN {role_permission} p ON r.rid = p.rid " + \
1819 "WHERE p.permission = '%s' ORDER BY r.name", permission)
1820 else:
1821 result = lib_database.query('SELECT * FROM {role} ORDER BY name')
1822 while True:
1823 role = lib_database.fetch_object(result)
1824
1825 if role.rid == DRUPAL_ANONYMOUS_RID:
1826 if (not membersonly):
1827 roles_[role.rid] = lib_common.t(role.name)
1828 elif role.rid == DRUPAL_AUTHENTICATED_RID:
1829 roles_[role.rid] = lib_common.t(role.name)
1830 else:
1831 roles_[role.rid] = role.name
1832
1833 return php.array_filter(roles_)
1834
1835
1836
1838 """
1839 Implementation of hook_user_operations().
1840 """
1841 operations = {
1842 'unblock' : {
1843 'label' : lib_common.t('Unblock the selected users'),
1844 'callback' : 'user_user_operations_unblock'
1845 },
1846 'block' : {
1847 'label' : lib_common.t('Block the selected users'),
1848 'callback' : 'user_user_operations_block'
1849 },
1850 'delete' : {
1851 'label' : lib_common.t('Delete the selected users')
1852 },
1853 }
1854 if (access('administer permissions')):
1855 roles_ = roles(True)
1856 del(roles_[DRUPAL_AUTHENTICATED_RID]);
1857 add_roles = []
1858 for key,value in roles_.items():
1859 add_roles['add_role-' + key] = value
1860 remove_roles = []
1861 for key,value in roles_.items():
1862 remove_roles['remove_role-' + key] = value
1863 if (php.count(roles_) > 0):
1864 role_operations = {
1865 lib_common.t('Add a role to the selected users') : {
1866 'label' : add_roles
1867 },
1868 lib_common.t('Remove a role from the selected users') : {
1869 'label' : remove_roles
1870 },
1871 }
1872 operations += role_operations
1873
1874
1875 if (not php.empty(form_state['submitted'])):
1876 operation_rid = php.explode('-', form_state['values']['operation'])
1877 operation = operation_rid[0]
1878 if (operation == 'add_role' or operation == 'remove_role'):
1879 rid = operation_rid[1]
1880 if (access('administer permissions')):
1881 operations[form_state['values']['operation']] = {
1882 'callback' : 'user_multiple_role_edit',
1883 'callback arguments' : (operation, rid),
1884 }
1885 else:
1886 watchdog('security', 'Detected malicious attempt to ' + \
1887 'alter protected user fields.', tuple(), WATCHDOG_WARNING)
1888 return
1889 return operations
1890
1891
1892
1894 """
1895 Callback function for admin mass unblocking users.
1896 """
1897 for uid in accounts:
1898 account = load({'uid' : int(uid)})
1899
1900 if (account != False and account.status == 0):
1901 save(account, {'status' : 1})
1902
1903
1904
1906 """
1907 Callback function for admin mass blocking users.
1908 """
1909 for uid in accounts:
1910 account = load({'uid' : int(uid)})
1911
1912 if (account != False and account.status == 1):
1913 save(account, {'status' : 0})
1914
1915
1916
1918 """
1919 Callback function for admin mass adding/deleting a user role.
1920 """
1921
1922
1923 role_name = lib_database.result(
1924 lib_database.query('SELECT name FROM {role} WHERE rid = %d', rid))
1925 if operation == 'add_role':
1926 for uid in accounts:
1927 account = load({'uid' : int(uid)})
1928
1929 if (account != False and not php.isset(account.roles[rid])):
1930 roles_ = account.roles + {rid : role_name}
1931 save(account, {'roles' : roles_})
1932 elif operation == 'remove_role':
1933 for uid in accounts:
1934 account = load({'uid' : int(uid)})
1935
1936 if (account != False and php.isset(account.roles[rid])):
1937 roles_ = php.array_diff(account.roles, {rid : role_name})
1938 save(account, {'roles' : roles})
1939
1940
1941
1943 php.Reference.check(form_state)
1944 edit = form_state['post']
1945 form['accounts'] = {'#prefix' : '<ul>', '#suffix' : '</ul>', '#tree' : True}
1946
1947 for uid,value in array_filter(edit['accounts']).items():
1948 user_ = lib_database.result(\
1949 lib_database.query('SELECT name FROM {users} WHERE uid = %d', uid))
1950 form['accounts'][uid] = {'#type' : 'hidden', '#value' : uid, \
1951 '#prefix' : '<li>', '#suffix' : check_plain(user_) + "</li>\n"}
1952 form['operation'] = {'#type' : 'hidden', '#value' : 'delete'}
1953 return confirm_form(form, \
1954 lib_common.t('Are you sure you want to delete these users?'), \
1955 'admin/user/user', lib_common.t('This action cannot be undone.'), \
1956 lib_common.t('Delete all'), lib_common.t('Cancel'))
1957
1958
1959
1960
1962 php.Reference.check(form_state)
1963 if (form_state['values']['confirm']):
1964 for uid, value in form_state['values']['accounts'].items():
1965 delete(form_state['values'], uid)
1966 drupal_set_message(lib_common.t('The users have been deleted.'))
1967 form_state['redirect'] = 'admin/user/user'
1968 return
1969
1970
1972 """
1973 Implementation of hook_help().
1974 """
1975 if path == 'admin/help#user':
1976 output = '<p>' + lib_common.t('The user module allows users to ' + \
1977 'register, login, and log out + Users benefit from being able ' + \
1978 'to sign on because it associates content they create with their ' + \
1979 'account and allows various permissions to be set for their roles. ' + \
1980 'The user module supports user roles which establish fine ' + \
1981 'grained permissions allowing each role to do only what ' + \
1982 'the administrator wants them to. Each user is assigned to ' + \
1983 'one or more roles. By default there are two roles ' + \
1984 '<em>anonymous</em> - a user who has not logged in, and ' + \
1985 '<em>authenticated</em> a user who has signed up and who ' + \
1986 'has been authorized.') + '</p>'
1987 output += '<p>' + lib_common.t("Users can use their own name or " + \
1988 "handle and can specify personal configuration settings through " + \
1989 "their individual <em>My account</em> page + Users must " + \
1990 "authenticate by supplying a local username and password or " + \
1991 "through their OpenID, an optional and secure method for " + \
1992 "logging into many websites with a single username and password. " + \
1993 "In some configurations, users may authenticate using a username " + \
1994 "and password from another Drupal site, or through some " + \
1995 "other site-specific mechanism.") + '</p>'
1996 output += '<p>' + lib_common.t('A visitor accessing your website ' + \
1997 'is assigned a unique ID, or session ID, which is stored in a ' + \
1998 'cookie + The cookie does not contain personal information, but ' + \
1999 'acts as a key to retrieve information from your site. ' + \
2000 'Users should have cookies enabled in their web browser ' + \
2001 'when using your site.') + '</p>'
2002 output += '<p>' + lib_common.t('For more information, see the online ' + \
2003 'handbook entry for <a href="@user">User module</a>.', \
2004 {'@user' : 'http://drupal.org/handbook/modules/user/'}) + '</p>'
2005 return output
2006 elif path == 'admin/user/user':
2007 return '<p>' + lib_common.t('Drupal allows users to register, login, ' + \
2008 'log out, maintain user profiles, etc + Users of the site ' + \
2009 'may not use their own names to post content until they have ' + \
2010 'signed up for a user account.') + '</p>'
2011 elif \
2012 path == 'admin/user/user/create' or \
2013 path == 'admin/user/user/account/create':
2014 return '<p>' + lib_common.t("This web page allows administrators " + \
2015 "to register new users. Users' e-mail addresses and " + \
2016 "usernames must be unique.") + '</p>'
2017 elif path == 'admin/user/permissions':
2018 return '<p>' + lib_common.t('Permissions let you control what users ' + \
2019 'can do on your site + Each user role (defined on the ' + \
2020 '<a href="@role">user roles page</a>) has its own set of ' + \
2021 'permissions. For example, you could give users classified ' + \
2022 'as "Administrators" permission to "administer nodes" but deny ' + \
2023 'this power to ordinary, "authenticated" users. You can use ' + \
2024 'permissions to reveal new features to privileged users ' + \
2025 '(those with subscriptions, for example). Permissions also allow '+ \
2026 'trusted users to share the administrative burden of ' + \
2027 'running a busy site.', {'@role' : url('admin/user/roles')}) + '</p>'
2028 elif path == 'admin/user/roles':
2029 return lib_common.t('<p>Roles allow you to fine tune the security and ' + \
2030 'administration of Drupal. A role defines a group of users ' + \
2031 'that have certain privileges as defined in ' + \
2032 '<a href="@permissions">user permissions</a>. Examples of ' + \
2033 'roles include: anonymous user, authenticated user, moderator, ' + \
2034 'administrator and so on. In this area you will define the ' + \
2035 '<em>role names</em> of the various roles. To delete a role ' + \
2036 'choose "edit".</p><p>By default, Drupal comes with two user ' + \
2037 'roles:</p><ul>' + \
2038 '<li>Anonymous user: this role is used for users that don\'t have ' + \
2039 'a user account or that are not authenticated.</li>' + \
2040 '<li>Authenticated user: this role is automatically granted ' + \
2041 'to all logged in users.</li></ul>', \
2042 {'@permissions' : url('admin/user/permissions')})
2043 elif path == 'admin/user/search':
2044 return '<p>' + lib_common.t('Enter a simple pattern ("*" may be ' + \
2045 'used as a wildcard match) to search for a username or ' + \
2046 'e-mail address + For example, one may search for "br" ' + \
2047 'and Drupal might return "brian", "brad", and ' + \
2048 '"brenda@example.com".') + '</p>'
2049
2050
2051
2053 """
2054 Retrieve a list of all user setting/information categories
2055 and sort them by weight.
2056 """
2057 categories = []
2058 for plugin in lib_plugin.list_():
2059 data = lib_plugin.invoke(plugin, 'user', 'categories', None, account, '')
2060 if data:
2061 categories = php.array_merge(data, categories)
2062 php.usort(categories, _sort)
2063 return categories
2064
2065
2066
2068 a = php.array_(a) + {'weight' : 0, 'title' : ''}
2069 b = php.array(b) + {'weight' : 0, 'title' : ''}
2070 return (-1 if (a['weight'] < b['weight']) else \
2071 (1 if (a['weight'] > b['weight']) else \
2072 (-1 if (a['title'] < b['title']) else 1)))
2073
2074
2076 """
2077 List user administration filters that can be applied.
2078 """
2079
2080 filters_ = []
2081 roles_ = roles(True)
2082 del(roles_[DRUPAL_AUTHENTICATED_RID]);
2083 if (php.count(roles_)):
2084 filters_['role'] = {
2085 'title' : lib_common.t('role'),
2086 'where' : "ur.rid = %d",
2087 'options' : roles_,
2088 'join' : ''
2089 }
2090 options = []
2091 for plugin in lib_plugin.list_():
2092 permissions = lib_plugin.invoke(plugin, 'perm')
2093 if permissions:
2094 php.asort(permissions)
2095 for permission,description in permissions.items():
2096 options[t('@module module', {'@module' : module})][permission] = \
2097 lib_common.t(permission)
2098 php.ksort(options)
2099 filters_['permission'] = {
2100 'title' : lib_common.t('permission'),
2101 'join' : 'LEFT JOIN {role_permission} p ON ur.rid = p.rid',
2102 'where' : " (p.permission = '%s' OR u.uid = 1) ",
2103 'options' : options
2104 }
2105 filters_['status'] = {
2106 'title' : lib_common.t('status'),
2107 'where' : 'u.status = %d',
2108 'join' : '',
2109 'options' : {1 : lib_common.t('active'), 0 : lib_common.t('blocked')}
2110 }
2111 return filters_
2112
2113
2114
2116 """
2117 Build query for user administration filters based on session.
2118 """
2119 filters_ = filters()
2120
2121 where = args = join_ = []
2122 for filter_ in php.SESSION['user_overview_filter']:
2123 key,value = filter_
2124
2125
2126
2127 if (key == 'permission'):
2128 account = php.stdClass()
2129 account.uid = 'user_filter'
2130 account.roles = {DRUPAL_AUTHENTICATED_RID : 1}
2131 if (access(value, account)):
2132 continue
2133 where.append( filters[key]['where'] )
2134 args.append( value )
2135 join_.append( filters[key]['join'] )
2136 where = ('AND ' + php.implode(' AND ', where) if \
2137 (not php.empty(where)) else '' )
2138 join_ = (' ' + php.implode(' ', php.array_unique(join_)) if \
2139 (not php.empty(join_)) else '')
2140 return {
2141 'where' : where,
2142 'join' : join_,
2143 'args' : args
2144 }
2145
2146
2155
2156
2157
2170
2171
2172
2174 """
2175 Theme output of user signature.
2176
2177 @ingroup themeable
2178 """
2179 output = ''
2180 if (signature):
2181 output += '<div class="clear">'
2182 output +='<div>--</div>'
2183 output += signature
2184 output += '</div>'
2185 return output
2186
2187
2188
2190 """
2191 Return an array of token to value mappings for user e-mail messages.
2192
2193 @param account
2194 The user object of the account being notified. Must contain at
2195 least the fields 'uid', 'name', and 'mail'.
2196 @param language
2197 Language object to generate the tokens with.
2198 @return
2199 Array of mappings from token names to values (for use with strtr()).
2200 """
2201 tokens = {
2202 'not username' : account.name,
2203 'not site' : lib_bootstrap.variable_get('site_name', 'Drupal'),
2204 'not login_url' : pass_reset_url(account),
2205 'not uri' : settings.base_url,
2206 'not uri_brief' : php.substr(settings.base_url, php.strlen('http://')),
2207 'not mailto' : account.mail,
2208 'not date' : format_date(php.time_(), 'medium', '', None, \
2209 language.language),
2210 'not login_uri' : url('user', {'absolute' : True, 'language' : language}),
2211 'not edit_uri' : url('user/' + account.uid + '/edit', \
2212 {'absolute' : True, 'language' : language})
2213 }
2214 if (not php.empty(account.password)):
2215 tokens['not password'] = account.password
2216 return tokens
2217
2218
2219
2221 """
2222 Get the language object preferred by the user. This user preference can
2223 be set on the user account editing page, and is only available if there
2224 are more than one languages enabled on the site. If the user did not
2225 choose a preferred language, or is the anonymous user, the default
2226 value, or if it is not set, the site default language will be returned.
2227
2228 @param account
2229 User account to look up language for.
2230 @param default
2231 Optional default language object to return if the account
2232 has no valid language.
2233 """
2234 language_list = lib_language.list_()
2235 if (account.language and php.isset(language_list[account.language])):
2236 return language_list[account.language]
2237 else:
2238 return (default if default else language_default())
2239
2240
2242 """
2243 Conditionally create and send a notification email when a certain
2244 operation happens on the given user account.
2245
2246 @see user_mail_tokens()
2247 @see drupal_mail()
2248
2249 @param op
2250 The operation being performed on the account. Possible values:
2251 'register_admin_created': Welcome message for user created by the admin
2252 'register_no_approval_required': Welcome message when user self-registers
2253 'register_pending_approval': Welcome message, user pending admin approval
2254 'password_reset': Password recovery request
2255 'status_activated': Account activated
2256 'status_blocked': Account blocked
2257 'status_deleted': Account deleted
2258
2259 @param account
2260 The user object of the account being notified. Must contain at
2261 least the fields 'uid', 'name', and 'mail'.
2262 @param language
2263 Optional language to use for the notification, overriding account language.
2264 @return
2265 The return value from drupal_mail_send(), if ends up being called.
2266 """
2267
2268 default_notify = (op != 'status_deleted' and op != 'status_blocked')
2269 notify = variable_get('user_mail_' + op + '_notify', default_notify)
2270 if (notify):
2271 params['account'] = account
2272 language = (language if language else user_preferred_language(account))
2273 mail = drupal_mail('user', op, account.mail, language, params)
2274 if (op == 'register_pending_approval'):
2275
2276
2277 drupal_mail('user', 'register_pending_approval_admin', \
2278 lib_bootstrap.variable_get('site_mail', ini_get('sendmail_from')), \
2279 lib_language.default(), params)
2280 return (None if php.empty(mail) else mail['result'])
2281
2282
2283
2285 """
2286 Add javascript and string translations for dynamic password validation
2287 (strength and confirmation checking).
2288
2289 This is an internal function that makes it easier to manage the translation
2290 strings that need to be passed to the javascript code.
2291 """
2292 php.static(_password_dynamic_validation, 'complete', False)
2293
2294 if (not complete):
2295 drupal_add_js(drupal_get_path('module', 'user') + '/user.js', 'module')
2296 drupal_add_js({
2297 'password' : {
2298 'strengthTitle' : lib_common.t('Password strength:'), \
2299 'lowStrength' : lib_common.t('Low'), \
2300 'mediumStrength' : lib_common.t('Medium'), \
2301 'highStrength' : lib_common.t('High'), \
2302 'tooShort' : lib_common.t('It is recommended to choose a ' + \
2303 'password that contains at least six characters. ' + \
2304 'It should include numbers, punctuation, and both ' + \
2305 'upper and lowercase letters.'), \
2306 'needsMoreVariation' : lib_common.t('The password does not ' + \
2307 'include enough variation to be secure + Try:'), \
2308 'addLetters' : lib_common.t('Adding both upper and ' + \
2309 'lowercase letters.'), \
2310 'addNumbers' : lib_common.t('Adding numbers.'), \
2311 'addPunctuation' : lib_common.t('Adding punctuation.'), \
2312 'sameAsUsername' : lib_common.t('It is recommended to choose ' + \
2313 'a password different from the username.'), \
2314 'confirmSuccess' : lib_common.t('Yes'), \
2315 'confirmFailure' : lib_common.t('No'), \
2316 'confirmTitle' : lib_common.t('Passwords match:'), \
2317 'username' : (user.name if php.isset(user.name) else '')}}, \
2318 'setting')
2319 complete = True
2320
2321
2323 """
2324 Implementation of hook_hook_info().
2325 """
2326 return {
2327 'user' : {
2328 'user' : {
2329 'insert' : {
2330 'runs when' : lib_common.t('After a user account has been created'),
2331 },
2332 'update' : {
2333 'runs when' : \
2334 lib_common.t("After a user's profile has been updated"),
2335 },
2336 'delete' : {
2337 'runs when' : lib_common.t('After a user has been deleted')
2338 },
2339 'login' : {
2340 'runs when' : lib_common.t('After a user has logged in')
2341 },
2342 'logout' : {
2343 'runs when' : lib_common.t('After a user has logged out')
2344 },
2345 'view' : {
2346 'runs when' : lib_common.t("When a user's profile is being viewed")
2347 }
2348 }
2349 }
2350 }
2351
2352
2353
2355 """
2356 Implementation of hook_action_info().
2357 """
2358 return {
2359 'user_block_user_action' : {
2360 'description' : lib_common.t('Block current user'),
2361 'type' : 'user',
2362 'configurable' : False,
2363 'hooks' : tuple()
2364 },
2365 }
2366
2367
2368
2370 """
2371 Implementation of a Drupal action.
2372 Blocks the current user.
2373 """
2374 php.Reference.check(object_)
2375 if (php.isset(object_.uid)):
2376 uid = object_.uid
2377 elif (isset(context['uid'])):
2378 uid = context['uid']
2379 else:
2380 uid = user.uid
2381 lib_database.query("UPDATE {users} SET status = 0 WHERE uid = %d", uid)
2382 lib_session.destroy_uid(uid)
2383 watchdog('action', 'Blocked user %name.', \
2384 {'%name' : check_plain(user.name)})
2385
2386
2387
2497
2498
2500 """
2501 Form builder; The user registration form.
2502
2503 @ingroup forms
2504 @see user_register_validate()
2505 @see user_register_submit()
2506 """
2507 admin = access('administer users')
2508
2509 if (not admin and user.uid):
2510 drupal_goto('user/' + user.uid)
2511 form = []
2512
2513 if (not admin):
2514 form['user_registration_help'] = \
2515 {'#markup' : filter_xss_admin(\
2516 lib_bootstrap.variable_get('user_registration_help', ''))}
2517
2518 form = php.array_merge(form, user_edit_form(form_state, None, None, True))
2519 if (admin):
2520 form['account']['notify'] = {
2521 '#type' : 'checkbox',
2522 '#title' : lib_common.t('Notify user of new account')
2523 }
2524
2525
2526 form['destination'] = {'#type' : 'hidden', '#value' : php.GET['q']}
2527
2528 null_ = php.Reference()
2529 extra = _forms(null_, None, None, 'register')
2530
2531 if (not extra):
2532 for key in ('name', 'mail', 'pass', 'status', 'roles', 'notify'):
2533 if (php.isset(form['account'][key])):
2534 form[key] = form['account'][key]
2535 del(form['account'])
2536 else:
2537 form = php.array_merge(form, extra)
2538 if (lib_bootstrap.variable_get('configurable_timezones', 1)):
2539
2540
2541 form['timezone'] = {
2542 '#type' : 'hidden',
2543 '#default_value' : \
2544 lib_bootstrap.variable_get('date_default_timezone', None),
2545 '#id' : 'edit-user-register-timezone'
2546 }
2547
2548 drupal_add_js(\
2549 'if (Drupal.jsEnabled) { ' + \
2550 ' $(document).ready(function() { ' + \
2551 ' Drupal.setDefaultTimezone(); ' + \
2552 ' }) ' + \
2553 '}', \
2554 'inline')
2555 form['submit'] = {'#type' : 'submit', '#value' : \
2556 lib_common.t('Create new account'), '#weight' : 30}
2557 form['#validate'].append( 'user_register_validate' )
2558 return form
2559
2560
2561
2566
2567
2580