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