When populating the $user->roles array in user_load(), line 174 and line 177 in version 6.9, the predefined roles are inserted 'as is', they don't get translated.

When modules try to discover permissions or load settings based on roles, they use the function user_roles(), which does role translating using t().

I discovered this bug when trying to blog to a German Drupal installation using Microsofts Windows Live Writer and accessing the xmlrpc interface using the WLW_BlogAPI module. Posting attachments was not possible due to not being able to figure out the permitted upload sizes for my role.

The lines in user.module should be:

172 $user->roles = array();
173 if ($user->uid) {
174 $user->roles[DRUPAL_AUTHENTICATED_RID] = t('authenticated user');
175 }
176 else {
177 $user->roles[DRUPAL_ANONYMOUS_RID] = t('anonymous user');
178 }

Comments

gábor hojtsy’s picture

Priority: Critical » Normal
Status: Active » Postponed (maintainer needs more info)

Modules use user_access() not user_roles() to look up permissions, since given roles cannot be assumed on the site. Looking into user_access() it does not care about the textual name of the role, but only about the key (internal role id).

Which modules do you see using user_roles()?

bkraegelin’s picture

Thanks for the reply.

I found the bug when trying to set up wlw_blogapi module for use with M$ Windows Live Writer. It rejected uploading images or other files.

The core module blogapi (wlw_blogapi is a textual daughter of it) does permission checking for allowed uploads in function blogapi_metaweblog_new_media_object() using array_intersect() of

- user_roles(FALSE, 'administer content with blog api')
// all roles, which have permission to use blogapi

- $user->roles
// roles, the logged in user belongs to

user_roles() gives 'Authentifizierter Benutzer' in the German Drupal installation, $user->roles gives 'authenticated user'.

As blogapi belongs to core, I consider this a serious bug.

gábor hojtsy’s picture

Status: Postponed (maintainer needs more info) » Needs review

Ok, seeing this at http://api.drupal.org/api/function/blogapi_metaweblog_new_media_object/6. Since the role numbers are only what is ever used in the function later, that function should just intersect the array keys, not the array values.

Something like:

  $roles = array_intersect(array_keys(user_roles(FALSE, 'administer content with blog api')), array_keys($user->roles));

  foreach ($roles as $rid) {
    // unchanged
  }

Can you try this change out? (Marking as patch needs review, although I've only described the required changes).

Once this is validated to work, it should be ported to both the core blogapi module and whatever descendants it has.

bkraegelin’s picture

Works, no question.
Remember Larry Wall's book on Perl: "There's More Than One Way To Do It".

My suggestion was, to get a consistent behaviour to user_roles(). So the user module would be consistent within itself.

Are there specific reasons, not to fix it in user_load()?

gábor hojtsy’s picture

It probably would be best to fix in user_load() as well, but that would require validation of all core and at least critical contributed module code where $user->roles or a derivative/copy/excerpt of $user->roles is used, so that it also assumes a translated role name.

bkraegelin’s picture

I can live with either... waiting for your decision.

I give the fix to the developers of wlw_blogapi. Core blogapi should be your responsibility.

gábor hojtsy’s picture

StatusFileSize
new1.18 KB

Here is all direct use of ->roles in Drupal 6 core:

$ grep -r "\->roles" *
includes/bootstrap.inc:  $user->roles = array();
includes/bootstrap.inc:  $user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user';
includes/file.inc:    foreach ($user->roles as $rid => $name) {
includes/session.inc:    $user->roles = array();
includes/session.inc:    $user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
includes/session.inc:      $user->roles[$role->rid] = $role->name;
modules/block/block.module:        $rids = array_keys($account->roles);
modules/block/block.module:    $rids = array_keys($user->roles);
modules/block/block.module:      $cid_parts[] = 'r.'. implode(',', array_keys($user->roles));
modules/blogapi/blogapi.module:  $roles = array_intersect(array_keys(user_roles(FALSE, 'administer content with blog api')), array_keys($user->roles));
modules/filter/filter.admin.inc:      if (strstr($format->roles, ",$rid,")) {
modules/filter/filter.admin.inc:    $checked = strstr($format->roles, ",$rid,");
modules/filter/filter.module:      foreach ($user->roles as $rid => $role) {
modules/upload/upload.module:  foreach ($user->roles as $rid => $name) {
modules/user/user.module:    $user->roles = array();
modules/user/user.module:      $user->roles[DRUPAL_AUTHENTICATED_RID] = 'authenticated user';
modules/user/user.module:      $user->roles[DRUPAL_ANONYMOUS_RID] = 'anonymous user';
modules/user/user.module:      $user->roles[$role->rid] = $role->name;
modules/user/user.module:    $result = db_query("SELECT p.perm FROM {role} r INNER JOIN {permission} p ON p.rid = r.rid WHERE r.rid IN (". db_placeholders($account->roles) .")", array_keys($account->roles));
modules/user/user.module:        if ($account !== FALSE && !isset($account->roles[$rid])) {
modules/user/user.module:          $roles = $account->roles + array($rid => $role_name);
modules/user/user.module:        if ($account !== FALSE && isset($account->roles[$rid])) {
modules/user/user.module:          $roles = array_diff($account->roles, array($rid => $role_name));
modules/user/user.module:      $account->roles = array(DRUPAL_AUTHENTICATED_RID => 1);

Here is a patch version of the above suggestion for review.

bkraegelin’s picture

Status: Needs review » Closed (fixed)

Sorry being late... waited for wlw_blogapi activity, closed on no activity

Fix tested, works.

damien tournoud’s picture

Version: 6.9 » 7.x-dev
Priority: Normal » Critical
Status: Closed (fixed) » Needs work

This needs to be fixed in D7, then backported.

By the way, we should really use array_diff_keys() here.

turbotad’s picture

Version: 7.x-dev » 6.13

Do you know if this has been integrated into the WLW module as yet? I am running into the same file upload bugs now as was described earlier, and have used what I thought was the most recent WLW blog api plugin.

bkraegelin’s picture

The corresponding Issue #346159: images permission problem had no activity, there seems to be no activity at all on wlw_blogapi.

Can be fixed like this in wlw_blogapi.module, Line 389 of Version 6.x-1.4 (Line 401 of Revision 1.16 of Head):

//  $roles = array_intersect(user_roles(0, 'administer content with blog api'), $user->roles);
  $roles = array_intersect(array_keys(user_roles(0, 'administer content with blog api')), array_keys($user->roles));
gábor hojtsy’s picture

Version: 6.13 » 7.x-dev

Damien was right this needs to be fixed in D7 first.

cem kaan’s picture

D7 i18n makes me worry about update.

catch’s picture

Version: 7.x-dev » 6.x-dev

Damien was right in July 2009, but in April 2010 blogapi module is no longer in core.

dpearcefl’s picture

Priority: Critical » Normal
Status: Needs work » Postponed (maintainer needs more info)

Is there any interest in this issue?

dpearcefl’s picture

Priority: Normal » Major
Status: Postponed (maintainer needs more info) » Needs work

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.