ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
ilMailRoleAddressType Class Reference

Class ilMailRoleAddressType. More...

+ Inheritance diagram for ilMailRoleAddressType:
+ Collaboration diagram for ilMailRoleAddressType:

Public Member Functions

 isValid ($a_sender_id)
 {} More...
 
 resolve ()
 {Returns an array of resolved user ids.
Returns
int[]
} More...
 
- Public Member Functions inherited from ilBaseMailAddressType
 __construct (\ilMailAddress $a_address)
 ilBaseMailAddressType constructor. More...
 
 validate ($a_sender_id)
 {
Parameters
$a_sender_idinteger
Returns
bool
} More...
 
 getErrors ()
 

Static Public Member Functions

static searchRolesByMailboxAddressList ( $a_address_list, ilMailRfc822AddressParserFactory $parserFactory=null, ilMailRfc822AddressParser $parser=null)
 Finds all role ids that match the specified user friendly role mailbox address list. More...
 
static getRoleMailboxAddress ( $a_role_id, $is_localize=true, ilMailRfc822AddressParserFactory $mailAddressParserFactory=null)
 Returns the mailbox address of a role. More...
 

Protected Member Functions

 maySendToGlobalRole ($a_sender_id)
 
- Protected Member Functions inherited from ilBaseMailAddressType
 init ()
 
 isValid ($a_sender_id)
 

Static Protected Member Functions

static getRoleIdsByAddress (ilMailAddress $a_address)
 

Static Protected Attributes

static $role_ids_by_address = array()
 
static $may_send_to_global_roles = array()
 

Additional Inherited Members

- Protected Attributes inherited from ilBaseMailAddressType
 $address
 
 $rbacsystem
 
 $rbacreview
 
 $errors = array()
 

Detailed Description

Member Function Documentation

◆ getRoleIdsByAddress()

static ilMailRoleAddressType::getRoleIdsByAddress ( ilMailAddress  $a_address)
staticprotected
Parameters
ilMailAddress$a_address
Returns
array

Definition at line 29 of file class.ilMailRoleAddressType.php.

References ilBaseMailAddressType\$address, ilMailAddress\getHost(), and ilMailAddress\getMailbox().

30  {
31  $address = $a_address->getMailbox() . '@' . $a_address->getHost();
32 
33  if (!isset(self::$role_ids_by_address[$address])) {
34  self::$role_ids_by_address[$address] = self::searchRolesByMailboxAddressList($address);
35  }
36 
37  return self::$role_ids_by_address[$address];
38  }
+ Here is the call graph for this function:

◆ getRoleMailboxAddress()

static ilMailRoleAddressType::getRoleMailboxAddress (   $a_role_id,
  $is_localize = true,
ilMailRfc822AddressParserFactory  $mailAddressParserFactory = null 
)
static

Returns the mailbox address of a role.

Example 1: Mailbox address for an ILIAS reserved role name

The il_crs_member_345 role of the course object "English Course 1" is returned as one of the following mailbox addresses:

a) Course Member <#member@[English Course 1]> b) Course Member <#il_crs_member_345@[English Course 1]> c) Course Member <#il_crs_member_345>

Address a) is returned, if the title of the object is unique, and if there is only one local role with the substring "member" defined for the object.

Address b) is returned, if the title of the object is unique, but there is more than one local role with the substring "member" in its title.

Address c) is returned, if the title of the course object is not unique.

Example 2: Mailbox address for a manually defined role name

The "Admin" role of the category object "Courses" is returned as one of the following mailbox addresses:

a) Course Administrator <#Admin> b) Course Administrator <#Admin> c) Course Adminstrator <#il_role_34211>

Address a) is returned, if the title of the object is unique, and if there is only one local role with the substring "Admin" defined for the course object.

Address b) is returned, if the title of the object is not unique, but the role title is unique.

Address c) is returned, if neither the role title nor the title of the course object is unique.

Example 3: Mailbox address for a manually defined role title that can contains special characters in the local-part of a

mailbox address

The "Author Courses" role of the category object "Courses" is returned as one of the following mailbox addresses:

a) "#Author Courses" b) Author Courses <#il_role_34234>

Address a) is returned, if the title of the role is unique.

Address b) is returned, if neither the role title nor the title of the course object is unique, or if the role title contains a quote or a backslash.

Parameters
$a_role_id
bool$is_localizeis_localize whether mailbox addresses should be localized
ilMailRfc822AddressParserFactory | null$mailAddressParserFactory
Returns
String mailbox address or null, if role does not exist.

Definition at line 357 of file class.ilMailRoleAddressType.php.

References $DIC, $domain, $parser, $query, $res, and $row.

Referenced by ilAbstractMailMemberRoles\getMailboxRoleAddress(), ilObjUserFolderGUI\importUserRoleAssignmentObject(), ilMailSearchCoursesGUI\mailCourses(), ilMailSearchGroupsGUI\mailGroups(), and ilObjRoleGUI\mailToRoleObject().

361  {
362  global $DIC;
363 
364  if ($mailAddressParserFactory === null) {
365  $mailAddressParserFactory = new ilMailRfc822AddressParserFactory();
366  }
367 
368  // Retrieve the role title and the object title.
369  $query = "SELECT rdat.title role_title,odat.title object_title, " .
370  " oref.ref_id object_ref " .
371  "FROM object_data rdat " .
372  "JOIN rbac_fa fa ON fa.rol_id = rdat.obj_id " .
373  "JOIN tree rtree ON rtree.child = fa.parent " .
374  "JOIN object_reference oref ON oref.ref_id = rtree.child " .
375  "JOIN object_data odat ON odat.obj_id = oref.obj_id " .
376  "WHERE rdat.obj_id = " . $DIC->database()->quote($a_role_id, 'integer') . " " .
377  "AND fa.assign = 'y' ";
378  $res = $DIC->database()->query($query);
379  if (!$row = $DIC->database()->fetchObject($res)) {
380  return null;
381  }
382 
383  $object_title = $row->object_title;
384  $object_ref = $row->object_ref;
385  $role_title = $row->role_title;
386 
387  // In a perfect world, we could use the object_title in the
388  // domain part of the mailbox address, and the role title
389  // with prefix '#' in the local part of the mailbox address.
390  $domain = $object_title;
391  $local_part = $role_title;
392 
393 
394  // Determine if the object title is unique
395  $q = "SELECT COUNT(DISTINCT dat.obj_id) count " .
396  "FROM object_data dat " .
397  "JOIN object_reference ref ON ref.obj_id = dat.obj_id " .
398  "JOIN tree ON tree.child = ref.ref_id " .
399  "WHERE title = " . $DIC->database()->quote($object_title, 'text') . " " .
400  "AND tree.tree = 1 ";
401  $res = $DIC->database()->query($q);
402  $row = $DIC->database()->fetchObject($res);
403 
404  // If the object title is not unique, we get rid of the domain.
405  if ($row->count > 1) {
406  $domain = null;
407  }
408 
409  // If the domain contains illegal characters, we get rid of it.
410  //if (domain != null && preg_match('/[\[\]\\]|[\x00-\x1f]/',$domain))
411  // Fix for Mantis Bug: 7429 sending mail fails because of brakets
412  // Fix for Mantis Bug: 9978 sending mail fails because of semicolon
413  if ($domain != null && preg_match('/[\[\]\\]|[\x00-\x1f]|[\x28-\x29]|[;]/', $domain)) {
414  $domain = null;
415  }
416 
417  // If the domain contains special characters, we put square
418  // brackets around it.
419  if ($domain != null &&
420  (preg_match('/[()<>@,;:\\".\[\]]/', $domain) ||
421  preg_match('/[^\x21-\x8f]/', $domain))
422  ) {
423  $domain = '[' . $domain . ']';
424  }
425 
426  // If the role title is one of the ILIAS reserved role titles,
427  // we can use a shorthand version of it for the local part
428  // of the mailbox address.
429  if (strpos($role_title, 'il_') === 0 && $domain != null) {
430  $unambiguous_role_title = $role_title;
431 
432  $pos = strpos($role_title, '_', 3) + 1;
433  $local_part = substr(
434  $role_title,
435  $pos,
436  strrpos($role_title, '_') - $pos
437  );
438  } else {
439  $unambiguous_role_title = 'il_role_' . $a_role_id;
440  }
441 
442  // Determine if the local part is unique. If we don't have a
443  // domain, the local part must be unique within the whole repositry.
444  // If we do have a domain, the local part must be unique for that
445  // domain.
446  if ($domain == null) {
447  $q = "SELECT COUNT(DISTINCT dat.obj_id) count " .
448  "FROM object_data dat " .
449  "JOIN object_reference ref ON ref.obj_id = dat.obj_id " .
450  "JOIN tree ON tree.child = ref.ref_id " .
451  "WHERE title = " . $DIC->database()->quote($local_part, 'text') . " " .
452  "AND tree.tree = 1 ";
453  } else {
454  $q = "SELECT COUNT(rd.obj_id) count " .
455  "FROM object_data rd " .
456  "JOIN rbac_fa fa ON rd.obj_id = fa.rol_id " .
457  "JOIN tree t ON t.child = fa.parent " .
458  "WHERE fa.assign = 'y' " .
459  "AND t.child = " . $DIC->database()->quote($object_ref, 'integer') . " " .
460  "AND rd.title LIKE " . $DIC->database()->quote(
461  '%' . preg_replace('/([_%])/', '\\\\$1', $local_part) . '%',
462  'text'
463  ) . " ";
464  }
465 
466  $res = $DIC->database()->query($q);
467  $row = $DIC->database()->fetchObject($res);
468 
469  // if the local_part is not unique, we use the unambiguous role title
470  // instead for the local part of the mailbox address
471  if ($row->count > 1) {
472  $local_part = $unambiguous_role_title;
473  }
474 
475  $use_phrase = true;
476 
477  // If the local part contains illegal characters, we use
478  // the unambiguous role title instead.
479  if (preg_match('/[\\"\x00-\x1f]/', $local_part)) {
480  $local_part = $unambiguous_role_title;
481  } elseif (!preg_match('/^[\\x00-\\x7E]+$/i', $local_part)) {
482  // 2013-12-05: According to #12283, we do not accept umlauts in the local part
483  $local_part = $unambiguous_role_title;
484  $use_phrase = false;
485  }
486 
487  // Add a "#" prefix to the local part
488  $local_part = '#' . $local_part;
489 
490  // Put quotes around the role title, if needed
491  if (preg_match('/[()<>@,;:.\[\]\x20]/', $local_part)) {
492  $local_part = '"' . $local_part . '"';
493  }
494 
495  $mailbox = ($domain == null) ?
496  $local_part :
497  $local_part . '@' . $domain;
498 
499  if ($is_localize) {
500  if (substr($role_title, 0, 3) == 'il_') {
501  $phrase = $DIC->language()->txt(substr($role_title, 0, strrpos($role_title, '_')));
502  } else {
503  $phrase = $role_title;
504  }
505 
506  if ($use_phrase) {
507  // make phrase RFC 822 conformant:
508  // - strip excessive whitespace
509  // - strip special characters
510  $phrase = preg_replace('/\s\s+/', ' ', $phrase);
511  $phrase = preg_replace('/[()<>@,;:\\".\[\]]/', '', $phrase);
512 
513  $mailbox = $phrase . ' <' . $mailbox . '>';
514  }
515  }
516 
517  try {
518  $parser = $mailAddressParserFactory->getParser($mailbox);
519  $parser->parse();
520 
521  return $mailbox;
522  } catch (ilException $e) {
523  $res = $DIC->database()->query("SELECT title FROM object_data WHERE obj_id = " . $DIC->database()->quote($a_role_id, 'integer'));
524  if ($row = $DIC->database()->fetchObject($res)) {
525  return '#' . $row->title;
526  } else {
527  return null;
528  }
529  }
530  }
global $DIC
Definition: saml.php:7
Class ilMailRfc822AddressParserFactory.
foreach($_POST as $key=> $value) $res
$query
$parser
Definition: BPMN2Parser.php:23
if(!array_key_exists('domain', $_REQUEST)) $domain
Definition: resume.php:8
+ Here is the caller graph for this function:

◆ isValid()

ilMailRoleAddressType::isValid (   $a_sender_id)

{}

Definition at line 65 of file class.ilMailRoleAddressType.php.

References array.

66  {
67  $role_ids = self::getRoleIdsByAddress($this->address);
68  if (!self::maySendToGlobalRole($a_sender_id)) {
69  foreach ($role_ids as $role_id) {
70  if ($this->rbacreview->isGlobalRole($role_id)) {
71  $this->errors[] = array('mail_to_global_roles_not_allowed', $this->address->getMailbox());
72  return false;
73  }
74  }
75  }
76 
77  if (count($role_ids) == 0) {
78  $this->errors[] = array('mail_recipient_not_found', $this->address->getMailbox());
79  return false;
80  } elseif (count($role_ids) > 1) {
81  $this->errors[] = array('mail_multiple_role_recipients_found', $this->address->getMailbox(), implode(',', $role_ids));
82  return false;
83  }
84 
85  return true;
86  }
Create styles array
The data for the language used.

◆ maySendToGlobalRole()

ilMailRoleAddressType::maySendToGlobalRole (   $a_sender_id)
protected
Parameters
int$a_sender_id
Returns
bool

Definition at line 44 of file class.ilMailRoleAddressType.php.

References ilMailGlobalServices\getMailObjectRefId().

45  {
46  if (!isset(self::$may_send_to_global_roles[$a_sender_id])) {
47  if ($a_sender_id == ANONYMOUS_USER_ID) {
48  self::$may_send_to_global_roles[$a_sender_id] = true;
49  } else {
50  require_once 'Services/Mail/classes/class.ilMailGlobalServices.php';
51  self::$may_send_to_global_roles[$a_sender_id] = $this->rbacsystem->checkAccessOfUser(
52  $a_sender_id,
53  'mail_to_global_roles',
55  );
56  }
57  }
58 
59  return self::$may_send_to_global_roles[$a_sender_id];
60  }
static getMailObjectRefId()
Determines the reference id of the mail object and stores this information in a local cache variable...
+ Here is the call graph for this function:

◆ resolve()

ilMailRoleAddressType::resolve ( )

{Returns an array of resolved user ids.

Returns
int[]
}

Implements ilMailAddressType.

Definition at line 91 of file class.ilMailRoleAddressType.php.

References array, and ilLoggerFactory\getLogger().

92  {
93  $usr_ids = array();
94 
95  $role_ids = self::getRoleIdsByAddress($this->address);
96 
97  if (count($role_ids) > 0) {
98  ilLoggerFactory::getLogger('mail')->debug(sprintf(
99  "Found the following role ids for address '%s': %s",
100  $this->address->getMailbox() . '@' . $this->address->getHost(),
101  implode(', ', array_unique($role_ids))
102  ));
103 
104  foreach ($role_ids as $role_id) {
105  foreach ($this->rbacreview->assignedUsers($role_id) as $usr_id) {
106  $usr_ids[] = $usr_id;
107  }
108  }
109 
110  if (count($usr_ids) > 0) {
111  ilLoggerFactory::getLogger('mail')->debug(sprintf(
112  "Found the following user ids for roles determined by address '%s': %s",
113  $this->address->getMailbox() . '@' . $this->address->getHost(),
114  implode(', ', array_unique($usr_ids))
115  ));
116  } else {
117  ilLoggerFactory::getLogger('mail')->debug(sprintf(
118  "Did not find any assigned users for roles determined by '%s'",
119  $this->address->getMailbox() . '@' . $this->address->getHost()
120  ));
121  }
122  } else {
123  ilLoggerFactory::getLogger('mail')->debug(sprintf(
124  "Did not find any role (and user ids) for address '%s'",
125  $this->address->getMailbox() . '@' . $this->address->getHost()
126  ));
127  }
128 
129  return array_unique($usr_ids);
130  }
Create styles array
The data for the language used.
static getLogger($a_component_id)
Get component logger.
+ Here is the call graph for this function:

◆ searchRolesByMailboxAddressList()

static ilMailRoleAddressType::searchRolesByMailboxAddressList (   $a_address_list,
ilMailRfc822AddressParserFactory  $parserFactory = null,
ilMailRfc822AddressParser  $parser = null 
)
static

Finds all role ids that match the specified user friendly role mailbox address list.

The role mailbox name address list is an e-mail address list according to IETF RFC 822:

address list = role mailbox, {"," role mailbox } ; role mailbox = "#", local part, ["@" domain] ;

Examples: The following role mailbox names are all resolved to the role il_crs_member_123:

#Course.A #member.A #il_crs_member_123.A #il_crs_member_123 #il_crs_member_123

Examples: The following role mailbox names are all resolved to the role il_crs_member_345:

#member@[English Course] #il_crs_member_345@[English Course] #il_crs_member_345 #il_crs_member_345

If only the local part is specified, or if domain is equal to "ilias", ILIAS compares the title of role objects with local part. Only roles that are not in a trash folder are considered for the comparison.

If a domain is specified, and if the domain is not equal to "ilias", ILIAS compares the title of objects with the domain. Only objects that are not in a trash folder are considered for the comparison. Then ILIAS searches for local roles which contain the local part in their title. This allows for abbreviated role names, e.g. instead of having to specify #il_grp_member_345, it is sufficient to specify #member.

The address list may contain addresses thate are not role mailboxes. These addresses are ignored.

If a role mailbox address is ambiguous, this function returns the ID's of all role objects that are possible recipients for the role mailbox address.

If Pear Mail is not installed, then the mailbox address

Parameters
$a_address_list
ilMailRfc822AddressParserFactory | null$parserFactory
ilMailRfc822AddressParser | null$parser
Returns
int[] Array with role ids that were found

Definition at line 179 of file class.ilMailRoleAddressType.php.

References ilBaseMailAddressType\$address, $DIC, $domain, $parser, $query, $res, $row, array, and ilMail\ILIAS_HOST.

Referenced by ilObjUserFolderGUI\importUserRoleAssignmentObject().

183  {
184  global $DIC;
185 
186  if ($parserFactory === null) {
187  $parserFactory = new ilMailRfc822AddressParserFactory();
188  }
189 
190  if ($parser === null) {
191  $parser = $parserFactory->getParser($a_address_list);
192  }
193 
194  $role_ids = array();
195  $parsedList = $parser->parse();
196 
197  foreach ($parsedList as $address) {
198  $local_part = $address->getMailbox();
199  if (strpos($local_part, '#') !== 0 && !($local_part{0} == '"' && $local_part{1} == "#")) {
200  // A local-part which doesn't start with a '#' doesn't denote a role.
201  // Therefore we can skip it.
202  continue;
203  }
204 
205  $local_part = substr($local_part, 1);
206 
207  /* If role contains spaces, eg. 'foo role', double quotes are added which have to be removed here.*/
208  if ($local_part{0} == '#' && $local_part{strlen($local_part) - 1} == '"') {
209  $local_part = substr($local_part, 1);
210  $local_part = substr($local_part, 0, strlen($local_part) - 1);
211  }
212 
213  if (substr($local_part, 0, 8) == 'il_role_') {
214  $role_id = substr($local_part, 8);
215  $query = "SELECT t.tree " .
216  "FROM rbac_fa fa " .
217  "JOIN tree t ON t.child = fa.parent " .
218  "WHERE fa.rol_id = " . $DIC->database()->quote($role_id, 'integer') . " " .
219  "AND fa.assign = 'y' " .
220  "AND t.tree = 1";
221  $res = $DIC->database()->query($query);
222  if ($DIC->database()->numRows($res) > 0) {
223  $role_ids[] = $role_id;
224  }
225  continue;
226  }
227 
228  $domain = $address->getHost();
229  if (strpos($domain, '[') == 0 && strrpos($domain, ']')) {
230  $domain = substr($domain, 1, strlen($domain) - 2);
231  }
232  if (strlen($local_part) == 0) {
233  $local_part = $domain;
234  $address->setHost(ilMail::ILIAS_HOST);
236  }
237 
238  if (strtolower($address->getHost()) == ilMail::ILIAS_HOST) {
239  // Search for roles = local-part in the whole repository
240  $query = "SELECT dat.obj_id " .
241  "FROM object_data dat " .
242  "JOIN rbac_fa fa ON fa.rol_id = dat.obj_id " .
243  "JOIN tree t ON t.child = fa.parent " .
244  "WHERE dat.title =" . $DIC->database()->quote($local_part, 'text') . " " .
245  "AND dat.type = 'role' " .
246  "AND fa.assign = 'y' " .
247  "AND t.tree = 1";
248  } else {
249  // Search for roles like local-part in objects = host
250  $query = "SELECT rdat.obj_id " .
251  "FROM object_data odat " .
252  "JOIN object_reference oref ON oref.obj_id = odat.obj_id " .
253  "JOIN tree otree ON otree.child = oref.ref_id " .
254  "JOIN rbac_fa rfa ON rfa.parent = otree.child " .
255  "JOIN object_data rdat ON rdat.obj_id = rfa.rol_id " .
256  "WHERE odat.title = " . $DIC->database()->quote($domain, 'text') . " " .
257  "AND otree.tree = 1 " .
258  "AND rfa.assign = 'y' " .
259  "AND rdat.title LIKE " .
260  $DIC->database()->quote('%' . preg_replace('/([_%])/', '\\\\$1', $local_part) . '%', 'text');
261  }
262  $res = $DIC->database()->query($query);
263 
264  $count = 0;
265  while ($row = $DIC->database()->fetchAssoc($res)) {
266  $role_ids[] = $row['obj_id'];
267 
268  $count++;
269  }
270 
271  // Nothing found?
272  // In this case, we search for roles = host.
273  if ($count == 0 && strtolower($address->getHost()) == ilMail::ILIAS_HOST) {
274  $q = "SELECT dat.obj_id " .
275  "FROM object_data dat " .
276  "JOIN object_reference ref ON ref.obj_id = dat.obj_id " .
277  "JOIN tree t ON t.child = ref.ref_id " .
278  "WHERE dat.title = " . $DIC->database()->quote($domain, 'text') . " " .
279  "AND dat.type = 'role' " .
280  "AND t.tree = 1 ";
281  $res = $DIC->database()->query($q);
282 
283  while ($row = $DIC->database()->fetchAssoc($res)) {
284  $role_ids[] = $row['obj_id'];
285  }
286  }
287  }
288 
289  return $role_ids;
290  }
const ILIAS_HOST
global $DIC
Definition: saml.php:7
Class ilMailRfc822AddressParserFactory.
foreach($_POST as $key=> $value) $res
$query
Create styles array
The data for the language used.
if(!array_key_exists('domain', $_REQUEST)) $domain
Definition: resume.php:8
+ Here is the caller graph for this function:

Field Documentation

◆ $may_send_to_global_roles

ilMailRoleAddressType::$may_send_to_global_roles = array()
staticprotected

Definition at line 23 of file class.ilMailRoleAddressType.php.

◆ $role_ids_by_address

ilMailRoleAddressType::$role_ids_by_address = array()
staticprotected

Definition at line 18 of file class.ilMailRoleAddressType.php.


The documentation for this class was generated from the following file: