ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilRoleMailboxAddress.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 {
24  protected ilDBInterface $db;
25  protected ilLanguage $lng;
26 
27  public function __construct(
28  protected int $role_id,
29  protected bool $localize = true,
30  ?ilMailRfc822AddressParserFactory $parser_factory = null,
31  ?ilDBInterface $db = null,
32  ?ilLanguage $lng = null
33  ) {
34  global $DIC;
35 
36  $this->db = $db ?? $DIC->database();
37  $this->lng = $lng ?? $DIC->language();
38  $this->parser_factory = $parser_factory ?? new ilMailRfc822AddressParserFactory();
39  }
40 
99  public function value(): string
100  {
101  // Retrieve the role title and the object title.
102  $query = 'SELECT rdat.title role_title, odat.title object_title, ' .
103  ' oref.ref_id object_ref ' .
104  'FROM object_data rdat ' .
105  'INNER JOIN role_data roledat ON roledat.role_id = rdat.obj_id ' .
106  'INNER JOIN rbac_fa fa ON fa.rol_id = rdat.obj_id AND fa.assign = ' . $this->db->quote('y', ilDBConstants::T_TEXT) . ' ' .
107  'INNER JOIN tree rtree ON rtree.child = fa.parent ' .
108  'INNER JOIN object_reference oref ON oref.ref_id = rtree.child ' .
109  'INNER JOIN object_data odat ON odat.obj_id = oref.obj_id ' .
110  'WHERE rdat.obj_id = ' . $this->db->quote($this->role_id, ilDBConstants::T_INTEGER);
111  $res = $this->db->query($query);
112  if (($row = $this->db->fetchObject($res)) === null) {
113  return '';
114  }
115 
116  $object_title = $row->object_title;
117  $object_ref = (int) $row->object_ref;
118  $role_title = $row->role_title;
119 
120  // In a perfect world, we could use the object_title in the
121  // domain part of the mailbox address, and the role title
122  // with prefix '#' in the local part of the mailbox address.
123  $domain = $object_title;
124  $local_part = $role_title;
125 
126  // Determine if the object title is unique (we exclude trashed obects)
127  $q = 'SELECT COUNT(DISTINCT dat.obj_id) AS count ' .
128  'FROM object_data dat ' .
129  'INNER JOIN object_reference ref ON ref.obj_id = dat.obj_id AND ref.deleted IS NULL ' .
130  'INNER JOIN tree ON tree.child = ref.ref_id AND tree.tree = ' . $this->db->quote(1, ilDBConstants::T_INTEGER) . ' ' .
131  'WHERE dat.title = ' . $this->db->quote($object_title, ilDBConstants::T_TEXT);
132  $res = $this->db->query($q);
133  $row = $this->db->fetchObject($res);
134 
135  // If the object title is not unique/does not exists, we get rid of the domain.
136  if ($row->count !== 1) {
137  $domain = null;
138  }
139 
140  // If the domain contains illegal characters, we get rid of it.
141  //if (domain != null && preg_match('/[\[\]\\]|[\x00-\x1f]/',$domain))
142  // Fix for Mantis Bug: 7429 sending mail fails because of brakets
143  // Fix for Mantis Bug: 9978 sending mail fails because of semicolon
144  if ($domain !== null && preg_match('/[\[\]\\]|[\x00-\x1f]|[\x28-\x29]|[;]/', (string) $domain)) {
145  $domain = null;
146  }
147 
148  // If the domain contains special characters, we put square
149  // brackets around it.
150  if ($domain !== null &&
151  (preg_match('/[()<>@,;:\\".\[\]]/', (string) $domain) ||
152  preg_match('/[^\x21-\x8f]/', (string) $domain))
153  ) {
154  $domain = '[' . $domain . ']';
155  }
156 
157  // If the role title is one of the ILIAS reserved role titles,
158  // we can use a shorthand version of it for the local part
159  // of the mailbox address.
160  if ($domain !== null && str_starts_with($role_title, 'il_')) {
161  $unambiguous_role_title = $role_title;
162 
163  $pos = strpos($role_title, '_', 3) + 1;
164  $local_part = substr(
165  $role_title,
166  $pos,
167  strrpos($role_title, '_') - $pos
168  );
169  } else {
170  $unambiguous_role_title = 'il_role_' . $this->role_id;
171  }
172 
173  // Determine if the local part is unique. If we don't have a
174  // domain, the local part must be unique within the whole repositry.
175  // If we do have a domain, the local part must be unique for that
176  // domain.
177  if ($domain === null) {
178  // https://mantis.ilias.de/view.php?id=45319
179  $q = 'SELECT COUNT(DISTINCT rdat.role_id) AS count ' .
180  'FROM object_data dat ' .
181  'INNER JOIN role_data rdat ON rdat.role_id = dat.obj_id ' .
182  'INNER JOIN rbac_fa fa ON fa.rol_id = rdat.role_id ' .
183  'INNER JOIN tree t ON t.child = fa.parent ' .
184  'INNER JOIN object_reference oref ON oref.ref_id = t.child ' .
185  'WHERE dat.title = ' . $this->db->quote($local_part, ilDBConstants::T_TEXT);
186  } else {
187  $q = 'SELECT COUNT(rd.obj_id) AS count ' .
188  'FROM object_data rd ' .
189  'INNER JOIN rbac_fa fa ON fa.rol_id = rd.obj_id AND fa.assign = ' . $this->db->quote('y', ilDBConstants::T_TEXT) . ' ' .
190  'INNER JOIN tree t ON t.child = fa.parent AND t.child = ' . $this->db->quote($object_ref, ilDBConstants::T_INTEGER) . ' ' .
191  'WHERE rd.title LIKE ' . $this->db->quote(
192  '%' . preg_replace('/([_%])/', '\\\\$1', $local_part) . '%',
194  ) . ' ';
195  }
196 
197  $res = $this->db->query($q);
198  $row = $this->db->fetchObject($res);
199 
200  // if the local_part is not unique, we use the unambiguous role title
201  // instead for the local part of the mailbox address
202  if ($row->count !== 1) {
203  $local_part = $unambiguous_role_title;
204  }
205 
206  $use_phrase = true;
207 
208  // If the local part contains illegal characters, we use
209  // the unambiguous role title instead.
210  if (preg_match('/[\\"\x00-\x1f]/', (string) $local_part)) {
211  $local_part = $unambiguous_role_title;
212  } elseif (!preg_match('/^[\\x00-\\x7E]+$/i', (string) $local_part)) {
213  // 2013-12-05: According to #12283, we do not accept umlauts in the local part
214  $local_part = $unambiguous_role_title;
215  $use_phrase = false;
216  }
217 
218  // Add a "#" prefix to the local part
219  $local_part = '#' . $local_part;
220 
221  // Put quotes around the role title, if needed
222  if (preg_match('/[()<>@,;:.\[\]\x20]/', $local_part)) {
223  $local_part = '"' . $local_part . '"';
224  }
225 
226  $mailbox = ($domain === null) ?
227  $local_part :
228  $local_part . '@' . $domain;
229 
230  if ($this->localize) {
231  if (str_starts_with($role_title, 'il_')) {
232  $phrase = $this->lng->txt(substr($role_title, 0, strrpos($role_title, '_')));
233  } else {
234  $phrase = $role_title;
235  }
236 
237  if ($use_phrase) {
238  // make phrase RFC 822 conformant:
239  // - strip excessive whitespace
240  // - strip special characters
241  $phrase = preg_replace('/\s\s+/', ' ', $phrase);
242  $phrase = preg_replace('/[()<>@,;:\\".\[\]]/', '', $phrase);
243 
244  $mailbox = $phrase . ' <' . $mailbox . '>';
245  }
246  }
247 
248  try {
249  $parser = $this->parser_factory->getParser($mailbox);
250  $parser->parse();
251 
252  return $mailbox;
253  } catch (ilMailException) {
254  $res = $this->db->query(
255  'SELECT od.title
256  FROM object_data od
257  INNER JOIN role_data rd ON rd.role_id = od.obj_id
258  WHERE od.obj_id = ' . $this->db->quote($this->role_id, ilDBConstants::T_INTEGER) . '
259  AND NOT EXISTS (
260  SELECT 1
261  FROM object_data maybe_same_role_od
262  INNER JOIN role_data maybe_same_role_rd ON maybe_same_role_rd.role_id = maybe_same_role_od.obj_id
263  WHERE maybe_same_role_od.title = od.title
264  AND maybe_same_role_od.obj_id != od.obj_id
265  )'
266  );
267  if (($row = $this->db->fetchObject($res)) !== null) {
268  return '#' . $row->title;
269  }
270 
271  return '#il_role_' . $this->role_id;
272  }
273  }
274 }
value()
Returns the mailbox address of a role.
$res
Definition: ltiservices.php:66
ilMailRfc822AddressParserFactory $parser_factory
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
global $DIC
Definition: shib_login.php:26
$q
Definition: shib_logout.php:23
__construct(protected int $role_id, protected bool $localize=true, ?ilMailRfc822AddressParserFactory $parser_factory=null, ?ilDBInterface $db=null, ?ilLanguage $lng=null)