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