ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilUtil.php
Go to the documentation of this file.
1 <?php
2 
23 
37 class ilUtil
38 {
44  public static function getImageTagByType(string $a_type, string $a_path, bool $a_big = false): string
45  {
46  global $DIC;
47 
48  $lng = $DIC->language();
49 
50  $size = ($a_big)
51  ? "big"
52  : "small";
53 
54  $filename = ilObject::_getIcon(0, $size, $a_type);
55 
56  return "<img src=\"" . $filename . "\" alt=\"" . $lng->txt("obj_" . $a_type) . "\" title=\"" . $lng->txt(
57  "obj_" . $a_type
58  ) . "\" border=\"0\" vspace=\"0\"/>";
59  }
60 
67  public static function getImagePath(
68  string $image_name,
69  string $module_path = "", // this parameter only supports "" value
70  string $mode = "output", // this parameter does not control anything anymore
71  bool $offline = false
72  ): string {
73  if ($offline) {
74  return "./images/" . $image_name;
75  }
76 
77  global $DIC;
78  $styleDefinition = $DIC["styleDefinition"] ?? null;
79 
80  if ($module_path != "") {
81  throw new \LogicException(
82  "\$module_path only supports '' as value."
83  );
84  }
85 
86  $use_custom_skin = (ilStyleDefinition::getCurrentSkin() !== "default");
87 
88  if ($use_custom_skin) {
89  $filename =
90  "./Customizing/skin/"
93  . (!is_object($styleDefinition) ? "images" : $styleDefinition->getImageDirectory(ilStyleDefinition::getCurrentStyle())) . "/"
94  . $image_name;
95 
96  if (file_exists($filename)) {
97  return $filename;
98  }
99  }
100 
101  return "./assets/images/" . $image_name;
102  }
103 
110  public static function getHtmlPath(string $relative_path): string
111  {
112  if (substr($relative_path, 0, 2) == './') {
113  $relative_path = (substr($relative_path, 1));
114  }
115  if (substr($relative_path, 0, 1) != '/') {
116  $relative_path = '/' . $relative_path;
117  }
118  $htmlpath = ILIAS_HTTP_PATH . $relative_path;
119  return $htmlpath;
120  }
121 
132  public static function getStyleSheetLocation(
133  string $mode = "output",
134  string $a_css_name = ""
135  ): string {
136  $force_reload = ($mode !== "filesystem");
137  $use_default_style_file = ($a_css_name === "");
138  $use_custom_skin = (ilStyleDefinition::getCurrentSkin() !== "default");
139 
140  // use ilStyleDefinition instead of account to get the current style
141 
142  if ($use_default_style_file) {
143  $stylesheet_name = ilStyleDefinition::getCurrentStyle() . ".css";
144  } else {
145  $stylesheet_name = $a_css_name;
146  }
147 
148  if ($use_custom_skin) {
149  $filename =
150  "./Customizing/skin/"
153  . $stylesheet_name;
154  } else {
155  $filename = "./assets/css/" . $stylesheet_name;
156  }
157 
158  if (!$force_reload) {
159  return $filename;
160  }
161 
162  // add version as parameter to force reload for new releases
163 
164  // use version from template xml to force reload on changes
166  $skin_version = $skin->getVersion();
167  if ($skin_version !== "") {
168  $skin_version_appendix = str_replace(".", "-", $skin_version);
169  } else {
170  $skin_version_appendix = '0';
171  }
172 
173  return $filename . "?skin_version=" . $skin_version_appendix;
174  }
175 
181  public static function getNewContentStyleSheetLocation(string $mode = "output"): string
182  {
183 
184  // use ilStyleDefinition instead of account to get the current skin and style
185  if (ilStyleDefinition::getCurrentSkin() == "default") {
186  $in_style = "./templates/" . ilStyleDefinition::getCurrentSkin() . "/"
187  . ilStyleDefinition::getCurrentStyle() . "_cont.css";
188  } else {
189  $in_style = "./Customizing/skin/" . ilStyleDefinition::getCurrentSkin() . "/"
190  . ilStyleDefinition::getCurrentStyle() . "_cont.css";
191  }
192 
193  if (is_file("./" . $in_style)) {
194  return $in_style;
195  } else {
196  return "assets/css/delos_cont.css";
197  }
198  }
199 
206  public static function switchColor(int $a_num, string $a_css1, string $a_css2): string
207  {
208  if (!($a_num % 2)) {
209  return $a_css1;
210  } else {
211  return $a_css2;
212  }
213  }
214 
219  public static function makeClickable(string $a_text, bool $detectGotoLinks = false): string
220  {
221  global $DIC;
222 
223  $ret = $DIC->refinery()->string()->makeClickable()->transform($a_text);
224 
225  if ($detectGotoLinks) {
226  $goto = '<a[^>]*href="(' . str_replace('@', '\@', ILIAS_HTTP_PATH) . '/goto';
227  $regExp = $goto . '.php\?target=\w+_(\d+)[^"]*)"[^>]*>[^<]*</a>';
228  $ret = preg_replace_callback(
229  '@' . $regExp . '@i',
230  [self::class, 'replaceLinkProperties'],
231  $ret
232  );
233 
234  // Edited this regex to allow multiple links in $ret: .* to [^"><]*.
235  $regExp = $goto . '_[^"><]*[a-z0-9]+_([0-9]+)\.html)"[^>]*>[^<]*</a>';
236  $ret = preg_replace_callback(
237  '@' . $regExp . '@i',
238  [self::class, 'replaceLinkProperties'],
239  $ret
240  );
241  }
242 
243  return $ret;
244  }
245 
246  private static function replaceLinkProperties(array $matches): string
247  {
248  global $DIC;
249  $cache = $DIC['ilObjDataCache'];
250 
251  $link = $matches[0];
252  $ref_id = (int) $matches[2];
253  if ($ref_id > 0) {
254  $obj_id = $cache->lookupObjId($ref_id);
255  if ($obj_id > 0) {
256  $title = $cache->lookupTitle($obj_id);
257  $link = '<a href="' . $matches[1] . '" target="_self">' . $title . '</a>';
258  }
259  }
260 
261  return $link;
262  }
263 
273  public static function is_email(
274  string $a_email,
275  ilMailRfc822AddressParserFactory $mailAddressParserFactory = null
276  ): bool {
277  if ($mailAddressParserFactory === null) {
278  $mailAddressParserFactory = new ilMailRfc822AddressParserFactory();
279  }
280 
281  try {
282  $parser = $mailAddressParserFactory->getParser($a_email);
283  $addresses = $parser->parse();
284  return count($addresses) == 1 && $addresses[0]->getHost() != ilMail::ILIAS_HOST;
285  } catch (ilException $e) {
286  return false;
287  }
288  }
289 
293  public static function isLogin(string $a_login): bool
294  {
295  if (empty($a_login)) {
296  return false;
297  }
298 
299  if (strlen($a_login) < 3) {
300  return false;
301  }
302 
303  // FIXME - If ILIAS is configured to use RFC 822
304  // compliant mail addresses we should not
305  // allow the @ character.
306  if (!preg_match("/^[A-Za-z0-9_\.\+\*\@!\$\%\~\-]+$/", $a_login)) {
307  return false;
308  }
309 
310  return true;
311  }
312 
319  public static function img(
320  string $a_src,
321  ?string $a_alt = null,
322  $a_width = "",
323  $a_height = "",
324  $a_border = 0,
325  $a_id = "",
326  $a_class = ""
327  ) {
328  $img = '<img src="' . $a_src . '"';
329  if (!is_null($a_alt)) {
330  $img .= ' alt="' . htmlspecialchars($a_alt) . '"';
331  }
332  if ($a_width != "") {
333  $img .= ' width="' . htmlspecialchars($a_width) . '"';
334  }
335  if ($a_height != "") {
336  $img .= ' height="' . htmlspecialchars($a_height) . '"';
337  }
338  if ($a_class != "") {
339  $img .= ' class="' . $a_class . '"';
340  }
341  if ($a_id != "") {
342  $img .= ' id="' . $a_id . '"';
343  }
344  $img .= ' />';
345 
346  return $img;
347  }
348 
352  public static function deliverData(
353  string $a_data,
354  string $a_filename,
355  string $mime = "application/octet-stream"
356  ): void {
357  global $DIC;
358  $delivery = new Delivery(
359  Delivery::DIRECT_PHP_OUTPUT,
360  $DIC->http()
361  );
362  $delivery->setMimeType($mime);
363  $delivery->setSendMimeType(true);
364  $delivery->setDisposition(Delivery::DISP_ATTACHMENT);
365  $delivery->setDownloadFileName($a_filename);
366  $delivery->setConvertFileNameToAsci(true);
367  $repsonse = $DIC->http()->response()->withBody(Streams::ofString($a_data));
368  $DIC->http()->saveResponse($repsonse);
369  $delivery->deliver();
370  }
371 
375  public static function appendUrlParameterString(string $a_url, string $a_par, bool $xml_style = false): string
376  {
377  $amp = $xml_style
378  ? "&amp;"
379  : "&";
380 
381  $url = (is_int(strpos($a_url, "?")))
382  ? $a_url . $amp . $a_par
383  : $a_url . "?" . $a_par;
384 
385  return $url;
386  }
387 
391  public static function stripSlashes(string $a_str, bool $a_strip_html = true, string $a_allow = ""): string
392  {
393  if (ini_get("magic_quotes_gpc")) {
394  $a_str = stripslashes($a_str);
395  }
396 
397  return ilUtil::secureString($a_str, $a_strip_html, $a_allow);
398  }
399 
403  public static function stripOnlySlashes(string $a_str): string
404  {
405  if (ini_get("magic_quotes_gpc")) {
406  $a_str = stripslashes($a_str);
407  }
408 
409  return $a_str;
410  }
411 
415  public static function secureString(string $a_str, bool $a_strip_html = true, string $a_allow = ""): string
416  {
417  // check whether all allowed tags can be made secure
418  $only_secure = true;
419  $allow_tags = explode(">", $a_allow);
420  $sec_tags = ilUtil::getSecureTags();
421  $allow_array = [];
422  foreach ($allow_tags as $allow) {
423  if ($allow != "") {
424  $allow = str_replace("<", "", $allow);
425 
426  if (!in_array($allow, $sec_tags)) {
427  $only_secure = false;
428  }
429  $allow_array[] = $allow;
430  }
431  }
432 
433  // default behaviour: allow only secure tags 1:1
434  if (($only_secure || $a_allow == "") && $a_strip_html) {
435  if ($a_allow === "") {
436  $allow_array = ["b",
437  "i",
438  "strong",
439  "em",
440  "code",
441  "cite",
442  "gap",
443  "sub",
444  "sup",
445  "pre",
446  "strike",
447  "bdo"
448  ];
449  }
450 
451  // this currently removes parts of strings like "a <= b"
452  // because "a <= b" is treated like "<spam onclick='hurt()'>ss</spam>"
453  $a_str = ilUtil::maskSecureTags($a_str, $allow_array);
454  $a_str = strip_tags($a_str); // strip all other tags
455  $a_str = ilUtil::unmaskSecureTags($a_str, $allow_array);
456 
457  // a possible solution could be something like:
458  // $a_str = str_replace("<", "&lt;", $a_str);
459  // $a_str = str_replace(">", "&gt;", $a_str);
460  // $a_str = ilUtil::unmaskSecureTags($a_str, $allow_array);
461  //
462  // output would be ok then, but input fields would show
463  // "a &lt;= b" for input "a <= b" if data is brought back to a form
464  } else {
465  // only for scripts, that need to allow more/other tags and parameters
466  if ($a_strip_html) {
467  $a_str = ilUtil::stripScriptHTML($a_str, $a_allow);
468  }
469  }
470 
471  return $a_str;
472  }
473 
474  public static function getSecureTags(): array
475  {
476  return ["strong",
477  "em",
478  "u",
479  "strike",
480  "ol",
481  "li",
482  "ul",
483  "p",
484  "div",
485  "i",
486  "b",
487  "code",
488  "sup",
489  "sub",
490  "pre",
491  "gap",
492  "a",
493  "img",
494  "bdo"
495  ];
496  }
497 
498  private static function maskSecureTags(string $a_str, array $allow_array): string
499  {
500  foreach ($allow_array as $t) {
501  switch ($t) {
502  case "a":
503  $a_str = ilUtil::maskAttributeTag($a_str, "a", "href");
504  break;
505 
506  case "img":
507  $a_str = ilUtil::maskAttributeTag($a_str, "img", "src");
508  break;
509 
510  case "p":
511  case "div":
512  $a_str = ilUtil::maskTag($a_str, $t, [
513  ["param" => "align", "value" => "left"],
514  ["param" => "align", "value" => "center"],
515  ["param" => "align", "value" => "justify"],
516  ["param" => "align", "value" => "right"]
517  ]);
518  break;
519 
520  default:
521  $a_str = ilUtil::maskTag($a_str, $t);
522  break;
523  }
524  }
525 
526  return $a_str;
527  }
528 
529  private static function unmaskSecureTags(string $a_str, array $allow_array): string
530  {
531  foreach ($allow_array as $t) {
532  switch ($t) {
533  case "a":
534  $a_str = ilUtil::unmaskAttributeTag($a_str, "a", "href");
535  break;
536 
537  case "img":
538  $a_str = ilUtil::unmaskAttributeTag($a_str, "img", "src");
539  break;
540 
541  case "p":
542  case "div":
543  $a_str = ilUtil::unmaskTag($a_str, $t, [
544  ["param" => "align", "value" => "left"],
545  ["param" => "align", "value" => "center"],
546  ["param" => "align", "value" => "justify"],
547  ["param" => "align", "value" => "right"]
548  ]);
549  break;
550 
551  default:
552  $a_str = ilUtil::unmaskTag($a_str, $t);
553  break;
554  }
555  }
556 
557  return $a_str;
558  }
559 
563  public static function securePlainString(string $a_str): string
564  {
565  if (ini_get("magic_quotes_gpc")) {
566  return stripslashes($a_str);
567  } else {
568  return $a_str;
569  }
570  }
571 
588  public static function htmlencodePlainString(
589  string $a_str,
590  bool $a_make_links_clickable,
591  bool $a_detect_goto_links = false
592  ): string {
593  $encoded = "";
594 
595  if ($a_make_links_clickable) {
596  // Find text sequences in the plain text string which match
597  // the URI syntax rules, and pass them to ilUtil::makeClickable.
598  // Encode all other text sequences in the plain text string using
599  // htmlspecialchars and nl2br.
600  // The following expressions matches URI's as specified in RFC 2396.
601  //
602  // The expression matches URI's, which start with some well known
603  // schemes, like "http:", or with "www.". This must be followed
604  // by at least one of the following RFC 2396 expressions:
605  // - alphanum: [a-zA-Z0-9]
606  // - reserved: [;\/?:|&=+$,]
607  // - mark: [\\-_.!~*\'()]
608  // - escaped: %[0-9a-fA-F]{2}
609  // - fragment delimiter: #
610  // - uric_no_slash: [;?:@&=+$,]
611  $matches = [];
612  $numberOfMatches = preg_match_all(
613  '/(?:(?:http|https|ftp|ftps|mailto):|www\.)(?:[a-zA-Z0-9]|[;\/?:|&=+$,]|[\\-_.!~*\'()]|%[0-9a-fA-F]{2}|#|[;?:@&=+$,])+/',
614  $a_str,
615  $matches,
616  PREG_OFFSET_CAPTURE
617  );
618  $pos1 = 0;
619  $encoded = "";
620 
621  foreach ($matches[0] as $match) {
622  $matched_text = $match[0];
623  $pos2 = $match[1];
624 
625  // encode plain text
626  $encoded .= nl2br(htmlspecialchars(substr($a_str, $pos1, $pos2 - $pos1)));
627 
628  // encode URI
629  $encoded .= ilUtil::makeClickable($matched_text, $a_detect_goto_links);
630 
631 
632  $pos1 = $pos2 + strlen($matched_text);
633  }
634  if ($pos1 < strlen($a_str)) {
635  $encoded .= nl2br(htmlspecialchars(substr($a_str, $pos1)));
636  }
637  } else {
638  $encoded = nl2br(htmlspecialchars($a_str));
639  }
640  return $encoded;
641  }
642 
643  private static function maskAttributeTag(string $a_str, string $tag, string $tag_att): string
644  {
645  global $DIC;
646 
647  $ilLog = $DIC["ilLog"];
648 
649  $ws = "[\s]*";
650  $att = $ws . "[^>]*" . $ws;
651 
652  while (preg_match(
653  '/<(' . $tag . $att . '(' . $tag_att . $ws . '="' . $ws . '(([$@!*()~;,_0-9A-z\/:=%.&#?+\-])*)")' . $att . ')>/i',
654  $a_str,
655  $found
656  )) {
657  $old_str = $a_str;
658  $a_str = preg_replace(
659  "/<" . preg_quote($found[1], "/") . ">/i",
660  '&lt;' . $tag . ' ' . $tag_att . $tag_att . '="' . $found[3] . '"&gt;',
661  $a_str
662  );
663  if ($old_str == $a_str) {
664  $ilLog->write(
665  "ilUtil::maskA-" . htmlentities($old_str) . " == " .
666  htmlentities($a_str)
667  );
668  return $a_str;
669  }
670  }
671  $a_str = str_ireplace(
672  "</$tag>",
673  "&lt;/$tag&gt;",
674  $a_str
675  );
676  return $a_str;
677  }
678 
679  private static function unmaskAttributeTag(string $a_str, string $tag, string $tag_att): string
680  {
681  global $DIC;
682 
683  $ilLog = $DIC["ilLog"];
684 
685  while (preg_match(
686  '/&lt;(' . $tag . ' ' . $tag_att . $tag_att . '="(([$@!*()~;,_0-9A-z\/:=%.&#?+\-])*)")&gt;/i',
687  $a_str,
688  $found
689  )) {
690  $old_str = $a_str;
691  $a_str = preg_replace(
692  "/&lt;" . preg_quote($found[1], "/") . "&gt;/i",
693  '<' . $tag . ' ' . $tag_att . '="' . ilUtil::secureLink($found[2]) . '">',
694  $a_str
695  );
696  if ($old_str == $a_str) {
697  $ilLog->write(
698  "ilUtil::unmaskA-" . htmlentities($old_str) . " == " .
699  htmlentities($a_str)
700  );
701  return $a_str;
702  }
703  }
704  $a_str = str_replace('&lt;/' . $tag . '&gt;', '</' . $tag . '>', $a_str);
705  return $a_str;
706  }
707 
708  public static function maskTag(string $a_str, string $tag, array $fix_param = []): string
709  {
710  $a_str = str_replace(
711  ["<$tag>", "<" . strtoupper($tag) . ">"],
712  "&lt;" . $tag . "&gt;",
713  $a_str
714  );
715  $a_str = str_replace(
716  ["</$tag>", "</" . strtoupper($tag) . ">"],
717  "&lt;/" . $tag . "&gt;",
718  $a_str
719  );
720 
721  foreach ($fix_param as $p) {
722  $k = $p["param"];
723  $v = $p["value"];
724  $a_str = str_replace(
725  "<$tag $k=\"$v\">",
726  "&lt;" . "$tag $k=\"$v\"" . "&gt;",
727  $a_str
728  );
729  }
730 
731  return $a_str;
732  }
733 
734  private static function unmaskTag(string $a_str, string $tag, array $fix_param = []): string
735  {
736  $a_str = str_replace("&lt;" . $tag . "&gt;", "<" . $tag . ">", $a_str);
737  $a_str = str_replace("&lt;/" . $tag . "&gt;", "</" . $tag . ">", $a_str);
738 
739  foreach ($fix_param as $p) {
740  $k = $p["param"];
741  $v = $p["value"];
742  $a_str = str_replace(
743  "&lt;$tag $k=\"$v\"&gt;",
744  "<" . "$tag $k=\"$v\"" . ">",
745  $a_str
746  );
747  }
748  return $a_str;
749  }
750 
754  public static function secureLink(string $a_str): string
755  {
756  $a_str = str_ireplace("javascript", "jvscrpt", $a_str);
757  $a_str = str_ireplace(["%00",
758  "%0a",
759  "%0d",
760  "%1a",
761  "&#00;",
762  "&#x00;",
763  "&#0;",
764  "&#x0;",
765  "&#x0a;",
766  "&#x0d;",
767  "&#10;",
768  "&#13;"
769  ], "-", $a_str);
770  return $a_str;
771  }
772 
776  public static function stripScriptHTML(string $a_str, string $a_allow = "", bool $a_rm_js = true): string
777  {
778  $negativestr = "a,abbr,acronym,address,applet,area,base,basefont," .
779  "big,blockquote,body,br,button,caption,center,cite,code,col," .
780  "colgroup,dd,del,dfn,dir,div,dl,dt,em,fieldset,font,form,frame," .
781  "frameset,h1,h2,h3,h4,h5,h6,head,hr,html,i,iframe,img,input,ins,isindex,kbd," .
782  "label,legend,li,link,map,menu,meta,noframes,noscript,object,ol," .
783  "optgroup,option,p,param,q,s,samp,script,select,small,span," .
784  "strike,strong,style,sub,sup,table,tbody,td,textarea,tfoot,th,thead," .
785  "title,tr,tt,u,ul,var";
786  $a_allow = strtolower($a_allow);
787  $negatives = explode(",", $negativestr);
788  $outer_old_str = "";
789  while ($outer_old_str != $a_str) {
790  $outer_old_str = $a_str;
791  foreach ($negatives as $item) {
792  $pos = strpos($a_allow, "<$item>");
793 
794  // remove complete tag, if not allowed
795  if ($pos === false) {
796  $old_str = "";
797  while ($old_str != $a_str) {
798  $old_str = $a_str;
799  $a_str = preg_replace("/<\/?\s*$item(\/?)\s*>/i", "", $a_str);
800  $a_str = preg_replace("/<\/?\s*$item(\/?)\s+([^>]*)>/i", "", $a_str);
801  }
802  }
803  }
804  }
805 
806  if ($a_rm_js) {
807  // remove all attributes if an "on..." attribute is given
808  $a_str = preg_replace("/<\s*\w*(\/?)(\s+[^>]*)?(\s+on[^>]*)>/i", "", $a_str);
809 
810  // remove all attributes if a "javascript" is within tag
811  $a_str = preg_replace("/<\s*\w*(\/?)\s+[^>]*javascript[^>]*>/i", "", $a_str);
812 
813  // remove all attributes if an "expression" is within tag
814  // (IE allows something like <b style='width:expression(alert(1))'>test</b>)
815  $a_str = preg_replace("/<\s*\w*(\/?)\s+[^>]*expression[^>]*>/i", "", $a_str);
816  }
817 
818  return $a_str;
819  }
820 
824  public static function secureUrl(string $url): string
825  {
826  // check if url is valid (absolute or relative)
827  if (filter_var($url, FILTER_VALIDATE_URL) === false &&
828  filter_var("http://" . $url, FILTER_VALIDATE_URL) === false &&
829  filter_var("http:" . $url, FILTER_VALIDATE_URL) === false &&
830  filter_var("http://de.de" . $url, FILTER_VALIDATE_URL) === false &&
831  filter_var("http://de.de/" . $url, FILTER_VALIDATE_URL) === false) {
832  return "";
833  }
834  if (trim(strtolower(parse_url($url, PHP_URL_SCHEME) ?? '')) === "javascript") {
835  return "";
836  }
837 
838  return htmlspecialchars($url, ENT_QUOTES);
839  }
840 
844  public static function extractParameterString(string $a_parstr): array
845  {
846  // parse parameters in array
847  $par = [];
848  $ok = true;
849  while (($spos = strpos($a_parstr, "=")) && $ok) {
850  // extract parameter
851  $cpar = substr($a_parstr, 0, $spos);
852  $a_parstr = substr($a_parstr, $spos, strlen($a_parstr) - $spos);
853  while (substr($cpar, 0, 1) == "," || substr($cpar, 0, 1) == " " || substr($cpar, 0, 1) == chr(13) || substr(
854  $cpar,
855  0,
856  1
857  ) == chr(10)) {
858  $cpar = substr($cpar, 1, strlen($cpar) - 1);
859  }
860  while (substr($cpar, strlen($cpar) - 1, 1) == " " || substr($cpar, strlen($cpar) - 1, 1) == chr(
861  13
862  ) || substr($cpar, strlen($cpar) - 1, 1) == chr(10)) {
863  $cpar = substr($cpar, 0, strlen($cpar) - 1);
864  }
865 
866  // parameter name should only
867  $cpar_old = "";
868  while ($cpar != $cpar_old) {
869  $cpar_old = $cpar;
870  $cpar = preg_replace("/[^a-zA-Z0-9_]/i", "", $cpar);
871  }
872 
873  // extract value
874  if ($cpar != "") {
875  if ($spos = strpos($a_parstr, "\"")) {
876  $a_parstr = substr($a_parstr, $spos + 1, strlen($a_parstr) - $spos);
877  $spos = strpos($a_parstr, "\"");
878  if (is_int($spos)) {
879  $cval = substr($a_parstr, 0, $spos);
880  $par[$cpar] = $cval;
881  $a_parstr = substr($a_parstr, $spos + 1, strlen($a_parstr) - $spos - 1);
882  } else {
883  $ok = false;
884  }
885  } else {
886  $ok = false;
887  }
888  }
889  }
890 
891  return $ok ? $par : [];
892  }
893 
897  public static function yn2tf(string $a_yn): bool
898  {
899  if (strtolower($a_yn) === "y") {
900  return true;
901  } else {
902  return false;
903  }
904  }
905 
909  public static function tf2yn(bool $a_tf): string
910  {
911  if ($a_tf) {
912  return "y";
913  } else {
914  return "n";
915  }
916  }
917 
923  public static function deducibleSize(string $a_mime): bool
924  {
925  if (($a_mime == "image/gif") || ($a_mime == "image/jpeg") ||
926  ($a_mime == "image/png") || ($a_mime == "application/x-shockwave-flash") ||
927  ($a_mime == "image/tiff") || ($a_mime == "image/x-ms-bmp") ||
928  ($a_mime == "image/psd") || ($a_mime == "image/iff")) {
929  return true;
930  } else {
931  return false;
932  }
933  }
934 
938  public static function redirect(string $a_script): void
939  {
940  global $DIC;
941 
942  if (!isset($DIC['ilCtrl']) || !$DIC['ilCtrl'] instanceof ilCtrl) {
943  (new InitCtrlService())->init($DIC);
944  }
945  $DIC->ctrl()->redirectToURL($a_script);
946  }
947 
955  public static function insertInstIntoID(string $a_value): string
956  {
957  if (substr($a_value, 0, 4) == "il__") {
958  $a_value = "il_" . IL_INST_ID . "_" . substr($a_value, 4, strlen($a_value) - 4);
959  }
960 
961  return $a_value;
962  }
963 
975  public static function groupNameExists(string $a_group_name, ?int $a_id = null): bool
976  {
977  global $DIC;
978 
979  $ilDB = $DIC->database();
980 
981  $ilErr = null;
982  if (isset($DIC["ilErr"])) {
983  $ilErr = $DIC["ilErr"];
984  }
985 
986  if (empty($a_group_name)) {
987  $message = __METHOD__ . ": No groupname given!";
988  $ilErr->raiseError($message, $ilErr->WARNING);
989  }
990 
991  $clause = ($a_id !== null) ? " AND obj_id != " . $ilDB->quote($a_id) . " " : "";
992 
993  $q = "SELECT obj_id FROM object_data " .
994  "WHERE title = " . $ilDB->quote($a_group_name, "text") . " " .
995  "AND type = " . $ilDB->quote("grp", "text") .
996  $clause;
997 
998  $r = $ilDB->query($q);
999 
1000  return $r->numRows() > 0;
1001  }
1002 
1006  public static function isWindows(): bool
1007  {
1008  return (strtolower(substr(php_uname(), 0, 3)) === "win");
1009  }
1010 
1016  public static function now(): string
1017  {
1018  return date("Y-m-d H:i:s");
1019  }
1020 
1049  public static function _getObjectsByOperations(
1050  $a_obj_type,
1051  string $a_operation,
1052  int $a_usr_id = 0,
1053  int $limit = 0
1054  ): array {
1055  global $DIC;
1056 
1057  $ilDB = $DIC->database();
1058  $rbacreview = $DIC->rbac()->review();
1059  $ilAccess = $DIC->access();
1060  $ilUser = $DIC->user();
1061  $ilSetting = $DIC->settings();
1062  $tree = $DIC->repositoryTree();
1063 
1064  if (!is_array($a_obj_type)) {
1065  $where = "WHERE type = " . $ilDB->quote($a_obj_type, "text") . " ";
1066  } else {
1067  $where = "WHERE " . $ilDB->in("type", $a_obj_type, false, "text") . " ";
1068  }
1069 
1070  // limit number of results default is search result limit
1071  if (!$limit) {
1072  $limit = (int) $ilSetting->get('search_max_hits', "100");
1073  }
1074  if ($limit == -1) {
1075  $limit = 10000;
1076  }
1077 
1078  // default to logged in usr
1079  $a_usr_id = $a_usr_id ?: $ilUser->getId();
1080  $a_roles = $rbacreview->assignedRoles($a_usr_id);
1081 
1082  // Since no rbac_pa entries are available for the system role. This function returns !all! ref_ids in the case the user
1083  // is assigned to the system role
1084  if ($rbacreview->isAssigned($a_usr_id, SYSTEM_ROLE_ID)) {
1085  $query = "SELECT ref_id FROM object_reference obr LEFT JOIN object_data obd ON obr.obj_id = obd.obj_id " .
1086  "LEFT JOIN tree ON obr.ref_id = tree.child " .
1087  $where .
1088  "AND tree = 1";
1089 
1090  $res = $ilDB->query($query);
1091  $counter = 0;
1092  $ref_ids = [];
1093  while ($row = $ilDB->fetchObject($res)) {
1094  // Filter recovery folder
1095  if ($tree->isGrandChild(RECOVERY_FOLDER_ID, $row->ref_id)) {
1096  continue;
1097  }
1098 
1099  if ($counter++ >= $limit) {
1100  break;
1101  }
1102 
1103  $ref_ids[] = $row->ref_id;
1104  }
1105  return $ref_ids;
1106  } // End Administrators
1107 
1108  // Check ownership if it is not asked for edit_permission or a create permission
1109  if ($a_operation == 'edit_permissions' or strpos($a_operation, 'create') !== false) {
1110  $check_owner = ") ";
1111  } else {
1112  $check_owner = "OR owner = " . $ilDB->quote($a_usr_id, "integer") . ") ";
1113  }
1114 
1115  $ops_ids = ilRbacReview::_getOperationIdsByName([$a_operation]);
1116  $ops_id = $ops_ids[0];
1117 
1118  $and = "AND ((" . $ilDB->in("rol_id", $a_roles, false, "integer") . " ";
1119 
1120  $query = "SELECT DISTINCT(obr.ref_id),obr.obj_id,type FROM object_reference obr " .
1121  "JOIN object_data obd ON obd.obj_id = obr.obj_id " .
1122  "LEFT JOIN rbac_pa ON obr.ref_id = rbac_pa.ref_id " .
1123  $where .
1124  $and .
1125  "AND (" . $ilDB->like("ops_id", "text", "%i:" . $ops_id . "%") . " " .
1126  "OR " . $ilDB->like("ops_id", "text", "%:\"" . $ops_id . "\";%") . ")) " .
1127  $check_owner;
1128 
1129  $res = $ilDB->query($query);
1130  $counter = 0;
1131  $ref_ids = [];
1132  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1133  if ($counter >= $limit) {
1134  break;
1135  }
1136 
1137  // Filter objects in recovery folder
1138  if ($tree->isGrandChild(RECOVERY_FOLDER_ID, $row->ref_id)) {
1139  continue;
1140  }
1141 
1142  // Check deleted, hierarchical access ...
1143  if ($ilAccess->checkAccessOfUser($a_usr_id, $a_operation, '', $row->ref_id, $row->type, $row->obj_id)) {
1144  $counter++;
1145  $ref_ids[] = $row->ref_id;
1146  }
1147  }
1148  return $ref_ids ?: [];
1149  }
1150 
1159  public static function isHTML(string $a_text): bool
1160  {
1161  if (strlen(strip_tags($a_text)) < strlen($a_text)) {
1162  return true;
1163  }
1164 
1165  return false;
1166  }
1167 
1174  public static function __extractRefId(string $role_title): ?int
1175  {
1176  $test_str = explode('_', $role_title);
1177  $prefix = $test_str[0] ?? '';
1178 
1179  if ($prefix === 'il') {
1180  $ref_id = $test_str[3] ?? null;
1181  return is_numeric($ref_id) ? (int) $ref_id : null;
1182  }
1183  return null;
1184  }
1185 
1194  public static function __extractId(string $ilias_id, int $inst_id): ?int
1195  {
1196  $test_str = explode('_', $ilias_id);
1197 
1198  $parsed_inst_id = (int) ($test_str[1] ?? 0);
1199  $prefix = $test_str[0] ?? '';
1200 
1201  if ($prefix === 'il' && $parsed_inst_id === $inst_id && count($test_str) === 4) {
1202  return is_numeric($test_str[3]) ? (int) $test_str[3] : null;
1203  }
1204  return null;
1205  }
1206 
1213  public static function _sortIds(array $a_ids, string $a_table, string $a_field, string $a_id_name): array
1214  {
1215  global $DIC;
1216 
1217  $ilDB = $DIC->database();
1218 
1219  if (!$a_ids) {
1220  return [];
1221  }
1222 
1223  // use database to sort user array
1224  $where = "WHERE " . $a_id_name . " IN (";
1225  $where .= implode(",", ilArrayUtil::quoteArray($a_ids));
1226  $where .= ") ";
1227 
1228  $query = "SELECT " . $a_id_name . " FROM " . $a_table . " " .
1229  $where .
1230  "ORDER BY " . $a_field;
1231 
1232  $res = $ilDB->query($query);
1233  $ids = [];
1234  while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
1235  $ids[] = $row->$a_id_name;
1236  }
1237  return $ids;
1238  }
1239 
1247  public static function getSystemMessageHTML(string $a_txt, string $a_type = "info")
1248  {
1249  global $DIC;
1250 
1251  $box_factory = $DIC->ui()->factory()->messageBox();
1252  switch ($a_type) {
1253  case 'info':
1254  $box = $box_factory->info($a_txt);
1255  break;
1256  case 'success':
1257  $box = $box_factory->success($a_txt);
1258  break;
1259  case 'question':
1260  $box = $box_factory->confirmation($a_txt);
1261  break;
1262  case 'failure':
1263  $box = $box_factory->failure($a_txt);
1264  break;
1265  default:
1266  throw new InvalidArgumentException();
1267  }
1268 
1269  return $DIC->ui()->renderer()->render($box);
1270  }
1271 
1275  public static function setCookie(
1276  string $a_cookie_name,
1277  string $a_cookie_value = '',
1278  bool $a_also_set_super_global = true,
1279  bool $a_set_cookie_invalid = false
1280  ): void {
1281  global $DIC;
1282 
1283  $http = $DIC->http();
1284  $cookie_jar = $http->cookieJar();
1285 
1286  $cookie_factory = new CookieFactoryImpl();
1287 
1288  $cookie_expire = null;
1289  if (defined('IL_COOKIE_EXPIRE') && is_numeric(IL_COOKIE_EXPIRE) && IL_COOKIE_EXPIRE > 0) {
1290  $cookie_expire = (int) IL_COOKIE_EXPIRE;
1291  }
1292 
1293  $expires = null;
1294  if ($a_set_cookie_invalid) {
1295  $expires = time() - 10;
1296  } elseif ($cookie_expire > 0) {
1297  $expires = time() + $cookie_expire;
1298  }
1299 
1300  $cookie = $cookie_factory->create($a_cookie_name, $a_cookie_value)
1301  ->withExpires($expires)
1302  ->withSecure(defined('IL_COOKIE_SECURE') ? IL_COOKIE_SECURE : false)
1303  ->withPath(defined('IL_COOKIE_PATH') ? IL_COOKIE_PATH : '')
1304  ->withDomain(defined('IL_COOKIE_DOMAIN') ? IL_COOKIE_DOMAIN : '')
1305  ->withHttpOnly(defined('IL_COOKIE_HTTPONLY') ? IL_COOKIE_HTTPONLY : false);
1306 
1307 
1308  if (
1309  defined('IL_COOKIE_SECURE') && IL_COOKIE_SECURE &&
1310  (!isset(session_get_cookie_params()['samesite']) || strtolower(session_get_cookie_params()['samesite']) !== 'strict')
1311  ) {
1312  $cookie = $cookie->withSamesite(Cookie::SAMESITE_LAX);
1313  }
1314  $jar = $cookie_jar->with($cookie);
1315  $response = $jar->renderIntoResponseHeader($http->response());
1316  $http->saveResponse($response);
1317  }
1318 
1322  public static function _getHttpPath(): string
1323  {
1324  global $DIC;
1325 
1326  $ilIliasIniFile = $DIC["ilIliasIniFile"];
1327 
1328  if ((isset($_SERVER['SHELL']) && $_SERVER['SHELL']) || PHP_SAPI === 'cli' ||
1329  // fallback for windows systems, useful in crons
1330  (class_exists("ilContext") && !ilContext::usesHTTP())) {
1331  return $ilIliasIniFile->readVariable('server', 'http_path');
1332  } else {
1333  return ILIAS_HTTP_PATH;
1334  }
1335  }
1336 
1351  public static function parseImportId(string $a_import_id): array
1352  {
1353  $exploded = explode('_', $a_import_id);
1354 
1355  $parsed['orig'] = $a_import_id;
1356  if ($exploded[0] == 'il') {
1357  $parsed['prefix'] = $exploded[0];
1358  }
1359  if (is_numeric($exploded[1])) {
1360  $parsed['inst_id'] = (int) $exploded[1];
1361  }
1362  $parsed['type'] = $exploded[2];
1363 
1364  if (is_numeric($exploded[3])) {
1365  $parsed['id'] = (int) $exploded[3];
1366  }
1367  return $parsed;
1368  }
1369 
1379  protected static function fmtFloat(
1380  float $a_float,
1381  int $a_decimals = 0,
1382  string $a_dec_point = null,
1383  string $a_thousands_sep = null,
1384  bool $a_suppress_dot_zero = false
1385  ): string {
1386  global $DIC;
1387 
1388  $lng = $DIC->language();
1389 
1390  if ($a_dec_point === null) {
1391  $a_dec_point = ".";
1392  }
1393  if ($a_dec_point === '-lang_sep_decimal-') {
1394  $a_dec_point = ".";
1395  }
1396 
1397  if ($a_thousands_sep === null) {
1398  $a_thousands_sep = $lng->txt('lang_sep_thousand');
1399  }
1400  if ($a_thousands_sep === '-lang_sep_thousand-') {
1401  $a_thousands_sep = ",";
1402  }
1403 
1404  $txt = number_format($a_float, $a_decimals, $a_dec_point, $a_thousands_sep);
1405 
1406  // remove trailing ".0"
1407  if (($a_suppress_dot_zero == 0 || $a_decimals == 0)
1408  && substr($txt, -2) == $a_dec_point . '0'
1409  ) {
1410  $txt = substr($txt, 0, strlen($txt) - 2);
1411  }
1412  if ($a_float == 0 and $txt == "") {
1413  $txt = "0";
1414  }
1415 
1416  return $txt;
1417  }
1418 
1435  public static function formatSize(int $size, string $a_mode = 'short', ?ilLanguage $a_lng = null): string
1436  {
1437  global $DIC;
1438 
1439  $lng = $DIC->language();
1440  if ($a_lng == null) {
1441  $a_lng = $lng;
1442  }
1443 
1444  $mag = 1024;
1445 
1446  if ($size >= $mag * $mag * $mag) {
1447  $scaled_size = $size / $mag / $mag / $mag;
1448  $scaled_unit = 'lang_size_gb';
1449  } else {
1450  if ($size >= $mag * $mag) {
1451  $scaled_size = $size / $mag / $mag;
1452  $scaled_unit = 'lang_size_mb';
1453  } else {
1454  if ($size >= $mag) {
1455  $scaled_size = $size / $mag;
1456  $scaled_unit = 'lang_size_kb';
1457  } else {
1458  $scaled_size = $size;
1459  $scaled_unit = 'lang_size_bytes';
1460  }
1461  }
1462  }
1463 
1464  $result = self::fmtFloat(
1465  $scaled_size,
1466  ($scaled_unit
1467  == 'lang_size_bytes') ? 0 : 1,
1468  $a_lng->txt('lang_sep_decimal'),
1469  $a_lng->txt('lang_sep_thousand'),
1470  true
1471  )
1472  . ' ' . $a_lng->txt($scaled_unit);
1473  if ($a_mode == 'long' && $size > $mag) {
1474  $result .= ' (' . self::fmtFloat(
1475  $size,
1476  0,
1477  $a_lng->txt('lang_sep_decimal'),
1478  $a_lng->txt('lang_sep_thousand')
1479  ) . ' '
1480  . $a_lng->txt('lang_size_bytes') . ')';
1481  }
1482 
1483  return $result;
1484  }
1485 }
setMimeType(string $mime_type)
Definition: Delivery.php:274
static getStyleSheetLocation(string $mode="output", string $a_css_name="")
get full style sheet file name (path inclusive) of current user
$res
Definition: ltiservices.php:69
static appendUrlParameterString(string $a_url, string $a_par, bool $xml_style=false)
static getSystemMessageHTML(string $a_txt, string $a_type="info")
Get HTML for a system message.
const IL_INST_ID
Definition: constants.php:40
static quoteArray(array $a_array)
Quotes all members of an array for usage in DB query statement.
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
Class InitCtrlService wraps the initialization of ilCtrl.
static is_email(string $a_email, ilMailRfc822AddressParserFactory $mailAddressParserFactory=null)
This preg-based function checks whether an e-mail address is formally valid.
const ILIAS_HOST
static usesHTTP()
Uses HTTP aka browser.
static isHTML(string $a_text)
Checks if a given string contains HTML or not.
static switchColor(int $a_num, string $a_css1, string $a_css2)
switches style sheets for each even $a_num (used for changing colors of different result rows) ...
const SYSTEM_ROLE_ID
Definition: constants.php:29
static secureString(string $a_str, bool $a_strip_html=true, string $a_allow="")
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static stripScriptHTML(string $a_str, string $a_allow="", bool $a_rm_js=true)
$response
Definition: xapitoken.php:90
static getImageTagByType(string $a_type, string $a_path, bool $a_big=false)
Builds an html image tag.
static maskTag(string $a_str, string $tag, array $fix_param=[])
static maskSecureTags(string $a_str, array $allow_array)
static replaceLinkProperties(array $matches)
static _getOperationIdsByName(array $operations)
get ops_id&#39;s by name.
static getSecureTags()
$url
Definition: shib_logout.php:63
static tf2yn(bool $a_tf)
$http
Definition: deliver.php:14
static deliverData(string $a_data, string $a_filename, string $mime="application/octet-stream")
static secureLink(string $a_str)
static secureUrl(string $url)
static img(string $a_src, ?string $a_alt=null, $a_width="", $a_height="", $a_border=0, $a_id="", $a_class="")
Build img tag.
static now()
Return current timestamp in Y-m-d H:i:s format.
$ilErr
Definition: raiseError.php:17
static isWindows()
static fmtFloat(float $a_float, int $a_decimals=0, string $a_dec_point=null, string $a_thousands_sep=null, bool $a_suppress_dot_zero=false)
format a float
static getNewContentStyleSheetLocation(string $mode="output")
get full style sheet file name (path inclusive) of current user
static htmlencodePlainString(string $a_str, bool $a_make_links_clickable, bool $a_detect_goto_links=false)
Encodes a plain text string into HTML for display in a browser.
Class ilMailRfc822AddressParserFactory.
$ilIliasIniFile
Definition: server.php:35
static unmaskAttributeTag(string $a_str, string $tag, string $tag_att)
$ref_id
Definition: ltiauth.php:66
static securePlainString(string $a_str)
static getCurrentSkin()
get the current skin use always this function instead of getting the account&#39;s skin the current skin ...
static setCookie(string $a_cookie_name, string $a_cookie_value='', bool $a_also_set_super_global=true, bool $a_set_cookie_invalid=false)
$_SERVER['HTTP_HOST']
Definition: raiseError.php:10
static formatSize(int $size, string $a_mode='short', ?ilLanguage $a_lng=null)
Returns the specified file size value in a human friendly form.
static isLogin(string $a_login)
global $DIC
Definition: shib_login.php:25
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
static unmaskSecureTags(string $a_str, array $allow_array)
static getHtmlPath(string $relative_path)
get url of path
static _getObjectsByOperations( $a_obj_type, string $a_operation, int $a_usr_id=0, int $limit=0)
Get all objects of a specific type and check access This function is not recursive, instead it parses the serialized rbac_pa entries.
$txt
Definition: error.php:30
static parseImportId(string $a_import_id)
Parse an ilias import id Typically of type il_[IL_INST_ID]_[OBJ_TYPE]_[OBJ_ID] returns array( &#39;orig&#39; ...
$filename
Definition: buildRTE.php:78
static _sortIds(array $a_ids, string $a_table, string $a_field, string $a_id_name)
Function that sorts ids by a given table field using WHERE IN E.g: __sort(array(6,7),&#39;usr_data&#39;,&#39;lastname&#39;,&#39;usr_id&#39;) => sorts by lastname.
static redirect(string $a_script)
static maskAttributeTag(string $a_str, string $tag, string $tag_att)
Class Delivery.
Definition: Delivery.php:38
static deducibleSize(string $a_mime)
checks if mime type is provided by getimagesize()
static _getHttpPath()
static extractParameterString(string $a_parstr)
global $ilSetting
Definition: privfeed.php:32
static __extractId(string $ilias_id, int $inst_id)
extract ref id from role title, e.g.
global $lng
Definition: privfeed.php:32
const RECOVERY_FOLDER_ID
Definition: constants.php:37
static groupNameExists(string $a_group_name, ?int $a_id=null)
checks if group name already exists.
$q
Definition: shib_logout.php:18
static yn2tf(string $a_yn)
static getCurrentStyle()
get the current style or sub style use always this function instead of getting the account&#39;s style th...
static unmaskTag(string $a_str, string $tag, array $fix_param=[])
static insertInstIntoID(string $a_value)
inserts installation id into ILIAS id
static makeClickable(string $a_text, bool $detectGotoLinks=false)
const IL_COOKIE_PATH(isset($_GET['client_id']))
Definition: index.php:47
static __extractRefId(string $role_title)
extract ref id from role title, e.g.
static stripOnlySlashes(string $a_str)
$r