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