EGOCMS  24.0
EGOTEC Content-Managament-System
Ego_System.php
gehe zur Dokumentation dieser Datei
1 <?php
15 {
20  // Für die Verwendung ohne Delimiter
21  const REGEX_EMAIL = '^[a-zA-Z0-9!#$%&\'*+\/=?^_`\{\|\}~\-]+(?:\.[a-zA-Z0-9!#$%&\'*+\/=?^_`\{\|\}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$';
22  // Für die Verwendung ohne Delimiter (und optional)
23  const REGEX_EMAIL_OPTIONAL = '^(|[a-zA-Z0-9!#$%&\'*+\/=?^_`\{\|\}~\-]+(?:\.[a-zA-Z0-9!#$%&\'*+\/=?^_`\{\|\}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?)$';
24  // Für die Verwendung mit / Delimiter
25  const REGEX_EMAIL_ESCAPED = '^[a-zA-Z0-9!#$%&\'*+\/=?^_`\{\|\}~\-]+(?:\.[a-zA-Z0-9!#$%&\'*+\/=?^_`\{\|\}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?$';
26 
27  // Das Admin Design
28  const ADMIN_SKIN = 'egotec';
29 
30  // Maximale Anzahl an Clusterservern
31  const MAX_CLUSTER = 10;
32 
34  1080 => '1920:1080',
35  720 => '1280:720',
36  360 => '640:360'
37  ];
38 
39  // Alle zum System gehörigen Dateien
40  public static $fileList = array(
41  'admin.php',
42  'favicon.ico',
43  'rewrite.php',
44  'json.php',
45  'url.php'
46  );
47 
48  public static $statusCodes = [
49  100 => 'Continue',
50  101 => 'Switching Protocols',
51  200 => 'OK',
52  201 => 'Created',
53  202 => 'Accepted',
54  203 => 'Non-Authoritative Information',
55  204 => 'No Content',
56  205 => 'Reset Content',
57  206 => 'Partial Content',
58  207 => 'Multi-Status',
59  208 => 'Already Reported',
60  226 => 'IM Used',
61  300 => 'Multiple Choices',
62  301 => 'Moved Permanently',
63  302 => 'Found',
64  303 => 'See Other',
65  304 => 'Not Modified',
66  305 => 'Use Proxy',
67  306 => '',
68  307 => 'Temporary Redirect',
69  308 => 'Permanent Redirect',
70  400 => 'Bad Request',
71  401 => 'Unauthorized',
72  402 => 'Payment Required',
73  403 => 'Forbidden',
74  404 => 'Not Found',
75  405 => 'Method Not Allowed',
76  406 => 'Not Acceptable',
77  407 => 'Proxy Authentication Required',
78  408 => 'Request Timeout',
79  409 => 'Conflict',
80  410 => 'Gone',
81  411 => 'Length Required',
82  412 => 'Precondition Failed',
83  413 => 'Request Entity Too Large',
84  414 => 'Request-URI Too Long',
85  415 => 'Unsupported Media Type',
86  416 => 'Requested Range Not Satisfiable',
87  417 => 'Expectation Failed',
88  420 => 'Policy Not Fulfilled',
89  421 => 'Misdirected Request',
90  422 => 'Unprocessable Entity',
91  423 => 'Locked',
92  424 => 'Failed Dependency',
93  426 => 'Upgrade Required',
94  428 => 'Precondition Required',
95  429 => 'Too Many Requests',
96  431 => 'Request Header Fields Too Large',
97  451 => 'Unavailable For Legal Reasons',
98  500 => 'Internal Server Error',
99  501 => 'Not Implemented',
100  502 => 'Bad Gateway',
101  503 => 'Service Unavailable',
102  504 => 'Gateway Timeout',
103  505 => 'HTTP Version Not Supported',
104  506 => 'Variant Also Negotiates',
105  507 => 'Insufficient Storage',
106  508 => 'Loop Detected',
107  509 => 'Bandwidth Limit Exceeded',
108  510 => 'Not Extended',
109  511 => 'Network Authentication Required'
110  ];
111 
118  private static $includedHtml = array();
119 
125  private static $fallbackMapping = array();
126 
132  private static $cache = array();
133 
139  private static $devMode = null;
140 
146  public static function loadGlobalConfig() {
147  if (self::file_exists($file = $GLOBALS['egotec_conf']['var_dir'] . 'conf/global.json')) {
148  $global = json_decode(self::file_get_contents($file), true);
149  } else {
150  $global = [];
151  }
152 
153  if (!empty($global)) {
162  $set_value = function($meta, $key) {
163  if (isset($meta['value'])) {
164  self::setAssocValue($GLOBALS['egotec_conf'], $key, $meta['value']);
165  } elseif (isset($meta['env'])) {
166  self::setAssocValue($GLOBALS['egotec_conf'], $key, $_ENV[$meta['env']]
167  ?? $_SERVER[$meta['env']]
168  ?? (getenv($meta['env'], true) ?: getenv($meta['env']))
169  );
170  }
171  };
172 
173  if (is_array($global['system'])) {
174  foreach ($global['system'] as $key => $meta) {
175  if (is_array($meta['values'])) {
176  foreach ($meta['values'] as $value) {
177  $set_value($value, $key);
178  }
179  } else {
180  $set_value($meta, $key);
181  }
182  }
183  }
184  }
185  }
186 
193  public static function isEmail($email) {
194  return (bool) preg_match('/'.self::REGEX_EMAIL_ESCAPED.'/msi', $email);
195  }
196 
203  public static function getDefaultRobots($default = '') {
204  if (Ego_System::file_exists($robots_file = $GLOBALS['egotec_conf']['egotec_dir'] . 'robots.txt')) {
205  return Ego_System::file_get_contents($robots_file);
206  }
207  return $default ?: 'User-agent: *';
208  }
209 
218  public static function escape($string, $esc_type = 'html', $char_set = 'UTF-8') {
219  switch ($esc_type) {
220  case 'html':
221  return htmlspecialchars($string, ENT_QUOTES, $char_set);
222 
223  case 'htmlall':
224  return htmlentities($string, ENT_QUOTES, $char_set);
225 
226  case 'url':
227  return rawurlencode($string);
228 
229  case 'urlpathinfo':
230  return str_replace('%2F','/',rawurlencode($string));
231 
232  case 'quotes':
233  // escape unescaped single quotes
234  return preg_replace("%(?<!\\\\)'%", "\\'", $string);
235 
236  case 'hex':
237  // escape every character into hex
238  $return = '';
239  for ($x=0; $x < strlen($string); $x++) {
240  $return .= '%' . bin2hex($string[$x]);
241  }
242  return $return;
243 
244  case 'hexentity':
245  $return = '';
246  for ($x=0; $x < strlen($string); $x++) {
247  $return .= '&#x' . bin2hex($string[$x]) . ';';
248  }
249  return $return;
250 
251  case 'decentity':
252  $return = '';
253  for ($x=0; $x < strlen($string); $x++) {
254  $return .= '&#' . ord($string[$x]) . ';';
255  }
256  return $return;
257 
258  case 'javascript':
259  // escape quotes and backslashes, newlines, etc.
260  return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
261 
262  case 'mail':
263  // safe way to display e-mail address on a web page
264  return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);
265 
266  case 'nonstd':
267  // escape non-standard chars, such as ms document quotes
268  $_res = '';
269  for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
270  $_ord = ord(substr($string, $_i, 1));
271  // non-standard char, escape it
272  if($_ord >= 126){
273  $_res .= '&#' . $_ord . ';';
274  }
275  else {
276  $_res .= substr($string, $_i, 1);
277  }
278  }
279  return $_res;
280  }
281  return $string;
282  }
283 
284  public static $allSites = array();
285 
292  public static function clearTypeCache($site_name = '') {
293  Ego_System::mkdir($GLOBALS['egotec_conf']['cache_dir']); // Falls das Cache Verzeichnis noch nicht existiert erzeugen.
294  $cache_dir = dir($GLOBALS['egotec_conf']['cache_dir']);
295  if ($cache_dir) {
296  while ($dir = $cache_dir->read()) {
297  if (
298  $dir[0] != '.'
299  && is_dir($cache_dir->path.$dir)
300  && (!$site_name || $dir == $site_name)
301  ) {
302  $directories = glob($cache_dir->path.$dir.'/types*');
303  if (is_array($directories)) {
304  foreach ($directories as $file) {
305  @unlink($file);
306  }
307  }
308  @unlink($cache_dir->path.$dir.'/classes.cache');
309  }
310  }
311  $cache_dir->close();
312  }
313  }
314 
318  public static function clearCache()
319  {
320  Ego_System::deldir($GLOBALS['egotec_conf']['cache_dir'], false);
322  Ego_System::mkdir($GLOBALS['egotec_conf']['cache_dir'].'compiled'.DIRECTORY_SEPARATOR.'_admin');
323  $path = '/';
324  switch ($GLOBALS['egotec_conf']['site_cache_type'])
325  {
326  case 'apcu':
327  require_once('base/Ego_Cache_apcu.php');
328  $cache = new Ego_Cache_apcu($path);
329  $cache->reset();
330  break;
331  case 'custom':
332  require_once($GLOBALS['egotec_conf']['var_dir'].'lib/Ego_Cache_custom.php');
333  $cache = new Ego_Cache_custom($path);
334  $cache->reset();
335  break;
336  default:
337  require_once('base/Ego_Cache_file.php');
338  $cache = new Ego_Cache_file($path);
339  $cache->reset();
340  }
341 
342  // Allgemeine Cache löschen
343  $cache = self::getCache();
344  $cache->reset();
345  }
346 
350  public static function clearNginxCache()
351  {
352  Ego_System::deldir($GLOBALS['egotec_conf']['var_dir'].'cachenginx', false);
353  }
354 
355  public static function clearMediaCache()
356  {
357  Ego_System::deldir($GLOBALS['egotec_conf']['cachemedia_dir'], false);
358  Ego_System::mkdir($GLOBALS['egotec_conf']['cachemedia_dir']);
359  $path = '/';
360  switch ($GLOBALS['egotec_conf']['site_cache_type'])
361  {
362  case 'apcu':
363  require_once('base/Ego_Cache_apcu.php');
364  $cache = new Ego_Cache_apcu($path);
365  $cache->reset();
366  break;
367  case 'custom':
368  require_once($GLOBALS['egotec_conf']['var_dir'].'lib/Ego_Cache_custom.php');
369  $cache = new Ego_Cache_custom($path);
370  $cache->reset();
371  break;
372  default:
373  require_once('base/Ego_Cache_file.php');
374  $cache = new Ego_Cache_file($path);
375  $cache->reset();
376  }
377  }
378 
379 
383  public static function clearCacheAllSites()
384  {
385  require_once('base/Site.php');
386  $dir = dir($GLOBALS['egotec_conf']['site_dir']);
387  while ($file = $dir->read())
388  {
389  if ($file['0']!='.' && is_dir($dir->path.$file))
390  {
391  try {
392  $site = new Site($file);
393  foreach ($site->getLanguages() as $lang)
394  {
395  $site->setLanguage($lang);
396  $site->clearCache();
397  }
398  } catch (Exception $e)
399  { // Verzeichnisse, die keinen Mandanten repräsentieren, ignorieren.
400  ;
401  }
402  }
403  }
405  }
406 
415  public static function pathinfo($string)
416  {
417  // pathinfo macht Probleme bei Umlauten als erstes Zeichen im Dateinamen.
418  $pos = strrpos($string, '/');
419  if ($pos === false)
420  {
421  $pos = strrpos($string, DIRECTORY_SEPARATOR);
422  }
423 
424  if ($pos === false)
425  {// Es taucht weder / noch \ auf
426  $string = ' '.$string;
427  } else {
428  $pos = ((int)$pos)+1;
429  $string = substr($string, 0, $pos).' '.substr($string, $pos);
430  }
431 
432  $result = pathinfo($string);
433  foreach($result as $key => $value)
434  {
435  $result[$key] = ltrim($value);
436  }
437  return $result;
438  }
439 
446  public static function basename($path)
447  {
448  $pathinfo = Ego_System::pathinfo($path);
449  return $pathinfo['basename'];
450  }
451 
460  public static function filterUnicode($s)
461  {
462  return preg_replace([
463  '/\x{2010}|\x{2011}|\x{2012}|\x{2013}|\x{2014}|\x{2015}|&ndash;|&mdash;/msiu',
464  '/\x{201c}|\x{201d}|\x{201e}|\x{201f}|&bdquo;|&ldquo;|&rdquo;/msiu',
465  '/\x{2018}|\x{2019}|\x{2020}|\x{201a}|\x{201b}|&sbquo;|&lsquo;|&rsquo;/msiu'
466  ], [
467  '-',
468  '"',
469  '\''
470  ], $s);
471  }
472 
481  public static function filterNonUtf8($s, $substitute = "", $strict = false)
482  {
483  /*// Diese Funktion ist nicht Oracle kompatibel
484  if (
485  Ego_System::getDbDriver() == 'oci'
486  || $GLOBALS['egotec_conf']['noutf8filter'] == 1
487  ) {
488  return $s;
489  }*/
490 
491  if (!$substitute) {
492  $substitute = "\xEF\xBF\xBD";
493  }
494 
495  if ($strict) {
496  // From http://stackoverflow.com/a/13695364 (ohne \xF0, \xE1)
497  $utf8_pattern = '/
498 ([\n\r\t\x20-\x7F]
499 |[\xC2-\xDF][\x80-\xBF]
500 | \xE0[\xA0-\xBF][\x80-\xBF]
501 | \xED[\x80-\x9F][\x80-\xBF]
502 |[\xF1-\xF3][\x80-\xBF]{3}
503 | \xF4[\x80-\x8F][\x80-\xBF]{2})
504 |(\xE0[\xA0-\xBF]
505 | \xED[\x80-\x9F]
506 |[\xF1-\xF3][\x80-\xBF]{1,2}
507 | \xF4[\x80-\x8F][\x80-\xBF]?)
508 /xs';
509  } else {
510  // From http://stackoverflow.com/a/13695364
511  $utf8_pattern = '/
512 ([\n\r\t\x20-\x7F]
513 |[\xC2-\xDF][\x80-\xBF]
514 | \xE0[\xA0-\xBF][\x80-\xBF]
515 |[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
516 | \xED[\x80-\x9F][\x80-\xBF]
517 | \xF0[\x90-\xBF][\x80-\xBF]{2}
518 |[\xF1-\xF3][\x80-\xBF]{3}
519 | \xF4[\x80-\x8F][\x80-\xBF]{2})
520 |(\xE0[\xA0-\xBF]
521 |[\xE1-\xEC\xEE\xEF][\x80-\xBF]
522 | \xED[\x80-\x9F]
523 | \xF0[\x90-\xBF][\x80-\xBF]?
524 |[\xF1-\xF3][\x80-\xBF]{1,2}
525 | \xF4[\x80-\x8F][\x80-\xBF]?)
526 /xs';
527  }
528 
529  // String der nur Utf8 Zeichen beinhaltet
530  $utf8_string = '';
531 
532  do {
533  $s2 = mb_substr($s, 0, 1000);
534  preg_replace_callback($utf8_pattern, function($matches) use ($substitute, &$utf8_string) {
535  if (isset($matches[2]) || isset($matches[3])) {
536  $utf8_string .= $substitute;
537  }
538  $utf8_string .= $matches[1];
539  return '';
540  }, $s2);
541  $s = mb_substr($s, 1000);
542  } while ($s);
543 
544  $utf8_string = str_replace("\xe2\x80".chr(168), " ", $utf8_string);
545 
546  if ($strict) {
547  return filter_var($utf8_string, FILTER_SANITIZE_SPECIAL_CHARS, FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_LOW);
548  }
549  return $utf8_string;
550  }
551 
558  public static function filterData($data)
559  {
560  if(is_array($data))
561  {
562  foreach($data as $key => $value)
563  {
564  if(is_array($value) || is_string($value))
565  {
566  $data[$key] = is_array($value) ? self::filterData($value) : self::filterNonUtf8($value);
567  }
568  }
569 
570  return $data;
571  }
572  else
573  {
574  return (is_string($data) ? self::filterNonUtf8($data) : $data);
575  }
576  }
577 
587  public static function checkEncoding($from='CP1252', $to='UTF-8', $original, $converted)
588  {
589  $converted2 = iconv($to, $from, $converted);
590  $converted2 = Ego_System::filterNonUtf8($converted2);
591  $original = Ego_System::filterNonUtf8($original);
592  if ($original === $converted2)
593  {
594  return true;
595  } else {
596  return false;
597  }
598  }
599 
615  public static function stringEncode($string, $from='UTF-8', $to='UTF-8')
616  {
617  if ($string == '') return $string;
618 
619  $source_encoding = array(
620  'CP1250','CP1251','CP1252','CP1253','CP1254','CP1255','CP1256','CP1257', //Weitere gängige Windows-Zeichensätze
621  'ISO-8859-2','ISO-8859-5','ISO-8859-1','ISO-8859-7','ISO-8859-9','ISO-8859-8','ISO-8859-6','ISO-8859-4', //Weitere gängige ISO-Zeichensätze
622  );
623 
624  $original = $string;
625  $converted = iconv($from, $to, $string);
626  $converted = Ego_System::filterNonUtf8($converted);
627 
628  if (Ego_System::checkEncoding($from, $to, $original, $converted))
629  {
630  return $converted;
631  } else {
632  foreach($source_encoding as $from)
633  {
634  $converted = iconv($from, $to, $string);
635  $converted = Ego_System::filterNonUtf8($converted);
636  if (Ego_System::checkEncoding($from, $to, $original, $converted))
637  {
638  return $converted;
639  }
640  }
641  return "Die Zeichenkette konnte leider nicht korrekt in UTF-8 umgewandelt werden.";
642  }
643  }
644 
651  public static function dateEncode($string) {
652  return strtotime($string);
653  }
654 
669  public static function mkdir($dir, $mode = 0755, $recursive = true) {
670  $mode = !empty($GLOBALS['egotec_conf']['chmod']) ? octdec($GLOBALS['egotec_conf']['chmod']) : $mode;
671  $dir = strtr($dir, '\\/', DIRECTORY_SEPARATOR.DIRECTORY_SEPARATOR);
672  $dir = str_replace('/./', '/', $dir);
673 
674  clearstatcache();
675 
676  if (!is_dir($dir)) {
677  if (@mkdir($dir, $mode, $recursive)) {
678  @chmod($dir, $mode);
679  clearstatcache();
680 
681  return true;
682  } else {
683  if ($GLOBALS['egotec_conf']['mkdir_warning']) {
684  egotec_warning_log('Filesystem-Fehler beim Anlegen von ' . $dir . "\n\n" . get_backtrace(0));
685  } else {
686  throw new Exception('Filesystem-Fehler beim Anlegen von ' . $dir);
687  }
688  }
689  }
690 
691  return false;
692  }
693 
719  public static function parseUrl($url) {
720  $info = [
721  'protokoll' => '',
722  'host' => '',
723  'port' => '',
724  'pfad' => '',
725  'datei' => '',
726  'query' => '',
727  'mark' => '',
728  'parameter' => [],
729  'parse_url' => '',
730  ];
731 
732  $parse_url = @parse_url($url);
733 
734  // parse_url kann bei kaputten URLs manchmal false liefern (https://www.php.net/manual/en/function.parse-url#refsect1-function.parse-url-returnvalues)
735  // Ab PHP 8.3 kommt es dann hier zu einem Fehler => bei kaputten URLs keine Informationen liefern
736  if ($parse_url !== false) {
737  $info['protokoll'] = $parse_url['scheme'];
738  $info['host'] = $parse_url['host'];
739  $info['port'] = $parse_url['port'];
740  $info['pfad'] = dirname($parse_url['path']);
741  $info['datei'] = basename($parse_url['path']);
742  $info['query'] = str_replace('&amp;', '&', $parse_url['query']);
743  $info['mark'] = $parse_url['fragment'];
744 
745  foreach (explode('&', $info['query']) as $param_pair) {
746  $key = strtok($param_pair, '=');
747  $value = strtok('=');
748  $info['parameter'][$key] = $value;
749  }
750 
751  $info['parse_url'] = $parse_url;
752  }
753 
754  return $info;
755  }
756 
763  public static function secureURL($url) {
764  if (
765  preg_match('/^.*?([?#]|$)/i', $url, $m1)
766  && preg_match('/^(.*\/)(.*)$/', $m1[0], $m2)
767  ) {
768  $pos = mb_strrpos($m2[2], '.');
769  if ($pos !== false) {
770  $suffix = rtrim(mb_substr($m2[2], $pos + 1), '?#');
771  if ($suffix != ($new_suffix = preg_replace('/^([a-z0-9]+).*?$/i', '$1', $suffix))) {
772  $url = $m2[1] . mb_substr($m2[2], 0, $pos) . '.' . $new_suffix . mb_substr($url, mb_strlen($m1[0]) - mb_strlen($m1[1]));
773  }
774  }
775  }
776  return $url;
777  }
778 
803  public static function deldir($location, $del=true, $without='',$rename=true)
804  {
805  if (!$location)
806  {
807  throw new Exception('deldir needs location not to be empty.');
808  }
809  set_time_limit(0);
810  if (substr($location,-1) != '/')
811  {
812  $location = $location.'/';
813  }
814  $location = strtr($location, '/', DIRECTORY_SEPARATOR);
815  if (is_dir($location))
816  {
817  $error = "Filesystem-Fehler beim Löschen von ".$location;
818 
819  if ($without)
820  { // Wenn Dateien oder Verzeichnisse beim löschen ausgelassen werden sollen,
821  $rename = false; // dann kann kein rename vorgenommen werden.
822  }
823 
824  $location = strtr($location, '/', DIRECTORY_SEPARATOR);
825  if (substr($location,-1) != DIRECTORY_SEPARATOR)
826  {
827  $location.= DIRECTORY_SEPARATOR;
828  }
829 
830  if (!Ego_System::file_exists($location))
831  {
832  return false;
833  }
834  if ($rename)
835  {
836  $tmp = $GLOBALS['egotec_conf']['tmp_dir'].'deldir_'.md5(microtime()).DIRECTORY_SEPARATOR;
837  while (Ego_System::file_exists($tmp))
838  {
839  $tmp = $GLOBALS['egotec_conf']['tmp_dir'].'deldir_'.md5(microtime()).DIRECTORY_SEPARATOR;
840  }
841  if (@rename($location,$tmp) === false)
842  { // Wenn verschieben nicht klappt, Unterverzeichnisse direkt löschen
843  if (is_dir($location))
844  {
845  $dir = dir($location);
846  while ($file = $dir->read())
847  {
848  if ($file[0]!='.')
849  {
850  if (is_dir($dir->path.$file)) {
851  self::deldir($dir->path.$file, true, '', false);
852  } else {
853  @unlink($dir->path.$file);
854  }
855  }
856  }
857  @rmdir($location);
858  return true;
859  }
860  }
861  if (!$del)
862  {//Soll das Verzeichnis selbst nicht gelöscht werden, muss es wieder erstellt werden
863  Ego_System::mkdir($location);
864  }
865  $location = $tmp;
866  }
867  $directory = dir($location);
868  $without_nodel = false; // Falls eine Ausnahme im Verzeichnis zurückbleibt, kann das Verzeichnis nicht gelöscht werden.
869  while (is_object($directory) && false !== ($file = $directory->read())) // #144288 : Hotfix, da es hier zu Abbrüchen kam, wegen fehlendem Objekt
870  {
871  set_time_limit(0);
872  if (! ( $without && $without[$file] ))
873  {
874  if (is_dir($directory->path.$file) && $file != '..' && $file != '.')
875  {
876  Ego_System::deldir($directory->path.$file, true, $without, false);
877  unset($file);
878  } elseif (is_file($directory->path.DIRECTORY_SEPARATOR.$file))
879  {
880  if (unlink($directory->path.$file) === false) throw new Exception($error);
881  unset($file);
882  }
883  } else {
884  $without_nodel = true; // Falls eine Ausnahme im Verzeichnis zurückbleibt, kann das Verzeichnis nicht gelöscht werden.
885  }
886  }
887  if (is_object($directory)) $directory->close(); // #144288 : Hotfix, da es hier zu Abbrüchen kam, wegen fehlendem Objekt
888  if ( !$without_nodel && false !== $del )
889  {
890  if ($rename)
891  {
892  Ego_System::deldir($location, true, '', false);
893  } else {
894  $pwd = getcwd();
895  chdir($GLOBALS['egotec_conf']['egotec_dir']);
896  $result = @rmdir($location);
897  @chdir($pwd);
898  if ($result)
899  {
900  return true;
901  } else {
902  throw new Exception($error);
903  }
904  }
905  }
906  } elseif (is_file($location)) {
907  @unlink($location);
908  return true;
909  }
910  return false;
911  }
912 
919  public static function flushHeaders($headers)
920  {
921  foreach ($headers as $key => $value)
922  {
923  header($key.': '.$value);
924  $GLOBALS['egotec']['response_headers'][$key] = $value;
925  }
926  }
927 
934  public static function flush($string = '') {
935  if ($GLOBALS['live_system_migrate'] || $GLOBALS['monitoring']) {
936  // Bei system_migrate über SOAP wird die Ausgabe zwischengespeichert
937  $GLOBALS['_output'] .= $string;
938  } else {
939  while (ob_get_level()) {
940  ob_end_flush();
941  }
942  ob_start();
943  if ($string) {
944  echo $string;
945  }
946  ob_end_flush();
947  flush();
948  }
949  }
950 
958  public static function endless($string = '', $flush = true) {
959  if (php_sapi_name() == 'fpm-fcgi') {
960  @self::header('X-Accel-Buffering: no'); // Buffering für Nginx deaktivieren
961  }
962  set_time_limit(0); // Endlose PHP Ausführungszeit
963  ignore_user_abort(true); // Skript weiter ausführen wenn Verbindung unterbrochen wird
964  @session_write_close(); // Session schließen
965  if ($flush) {
966  self::flush($string); // Kein Browser Timeout
967  }
968  }
969 
977  public static function write_ini_file($path, $assoc_array = array()) {
986  $clean = function($array) use (&$clean) {
987  foreach ($array as $key => $value) {
988  if (is_array($value)) {
989  $array[$key] = $clean($value);
990  } else {
991  $value = mb_strtolower($value);
992  if ($value === 'null' || $value === 'false') {
993  $array[$key] = '';
994  } else if ($value === 'true') {
995  $array[$key] = '1';
996  }
997  $array[$key] = str_replace('"', '\"', str_replace('\"', '"', $array[$key]));
998  }
999  }
1000  return $array;
1001  };
1002  $assoc_array = $clean($assoc_array);
1003 
1004  $path = strtr($path, '/', DIRECTORY_SEPARATOR);
1005  $single_content = $assoc_content = '';
1006  foreach ($assoc_array as $key => $item) {
1007  if (is_array($item)) {
1008  $assoc_content.= "\n[".$key."]\n";
1009  foreach ($item as $key2 => $item2) {
1010  if ($item2 != 'Array') { // Dreistufige Konfigurationen direkt aus der local.php nicht in die ini schreiben
1011  $assoc_content.= $key2.'="'.$item2.'"'."\n";
1012  }
1013  }
1014  } else {
1015  $single_content.= $key.'="'.$item.'"'."\n";
1016  }
1017  }
1018  $content = $single_content."\n".$assoc_content;
1019  if (!$handle = @fopen($path, 'w')) {
1020  return false;
1021  }
1022  if (!@fwrite($handle, $content)) {
1023  return false;
1024  }
1025  @fclose($handle);
1026  return true;
1027  }
1028 
1043  public static function header($header, $replace = true)
1044  {
1045  if (is_numeric($header)) {
1046  // 403 Antworten an MS Word immer als 200 senden
1047  if ($header == 403 && preg_match('/(Microsoft Office Word|ms-office)/i', $_SERVER['HTTP_USER_AGENT'])) {
1048  $header = 200;
1049  }
1050  $code = $header;
1051 
1052  // Status Code Header
1053  if (isset(self::$statusCodes[$header])) {
1054  $GLOBALS['stats']['status'] = $header;
1055  $GLOBALS['_SERVER']['REDIRECT_STATUS'] = $header;
1056  $header = ($_SERVER['SERVER_PROTOCOL'] ?? '') . ' ' . $header . ' ' . self::$statusCodes[$header];
1057  } else {
1058  throw new Exception('Unsupported HTTP Status Code');
1059  }
1060 
1061  // Die originale ID merken, wenn ein 404 Header ausgegeben wird
1062  if ($code == 404 && !empty($_REQUEST['id'])) {
1063  $_REQUEST['original_id'] = $_REQUEST['id'];
1064  }
1065  }
1066  header($header, $replace);
1067  $pos = strpos($header, ':');
1068  $key = substr($header, 0, $pos);
1069  $value = trim(substr($header, $pos+1));
1070  if ($pos === false) {
1071  $key = $header;
1072  $value = '';
1073  }
1074  if (!$replace && isset($GLOBALS['egotec']['response_headers'][$key])) {
1075  $GLOBALS['egotec']['response_headers'][$key] .= ", $value";
1076  } else {
1077  $GLOBALS['egotec']['response_headers'][$key] = $value;
1078  }
1079  }
1080 
1087  public static function noCache()
1088  {
1089  self::header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
1090  self::header('Cache-Control: no-store, no-cache, must-revalidate');
1091  self::header('Cache-Control: post-check=0, pre-check=0', false);
1092  self::header('Pragma: no-cache');
1093  $GLOBALS['no_cache'] = true;
1094  }
1095 
1103  public static function setIntranetReferer($page) {
1104  if (!$_REQUEST['doauth']) { // Referer merken, um nach dem erfolgreichen Anmelden dorthin zu springen.
1105  $_SESSION['intranet_referer'] = str_replace('-doauth-logout', '', (
1106  $_SESSION['redirect_referer'] ?? $_SERVER['HTTP_REFERER'] ?? $_SERVER['REDIRECT_URL'] ?? $_SERVER['REQUEST_URI']
1107  ));
1108 
1109  // Letzte Seite vor dem Login anzeigen
1110  if (in_array($page->extra['next_page'], ['last', 'current' /* abwärtskompatibel */]) || !$_SESSION['intranet_referer']) {
1111  $_SESSION['intranet_referer'] = str_replace('-doauth-logout', '', $_SERVER['REQUEST_URI']);
1112  }
1113 
1114  }
1115  }
1116 
1128  public static function redirect($location, $header = 302, $params = []) {
1129  if (!empty($header)) {
1130  self::header($header);
1131  }
1132  if (is_a($location, 'Page')) {
1133  $location = $location->getUrl($params);
1134  }
1135  self::header("Location: $location");
1136  exit;
1137  }
1138 
1147  public static function checkLicence($ini_path)
1148  {
1149  unset($_SESSION['egotec_licence'][$ini_path]);
1150 
1151  if (isset($_SESSION['egotec_licence'][$ini_path]))
1152  {
1153  return $_SESSION['egotec_licence'][$ini_path];
1154  } else {
1155  $ini_file = rtrim($ini_path,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'module.ini';
1156  if (Ego_System::file_exists($ini_file))
1157  {
1158  $module = parse_ini_file($ini_file);
1159  $licence_array = file($GLOBALS['egotec_conf']['var_dir']
1160  .'co'.'nf'.'/'.'l'.'ic'.'en'.'ce'.'.'.'eg'.'ot'.'ec'.'.'.'x'.'ml');
1161  $company = trim($licence_array[4]);
1162  $num_named_users = trim($licence_array[7]);
1163  foreach($licence_array as $key => $value)
1164  {
1165  if (trim($value) == '<module_'.$module['name'].'>')
1166  {
1167  if (trim($licence_array[$key+1]) == md5('2u4z#h76CN~JBSo'.$company.$num_named_users.$module['name']))
1168  {
1169  return $_SESSION['egotec_licence'][$ini_path] = true;
1170  }
1171  }
1172  }
1173  }
1174  }
1175  return $_SESSION['egotec_licence'][$ini_path] = false;
1176  }
1177 
1186  public static function setCronLock($expiry_date = 0, $lock_msg = "") {
1187  if ($GLOBALS['cron_fix_services']) {
1188  return;
1189  }
1190 
1191  $original_expiry_date = $expiry_date;
1192  $original_lock_msg = $lock_msg;
1193 
1194  $lock_file = $GLOBALS['egotec_conf']['log_dir'].'CRON'.((string)$GLOBALS['__CRON_LOCK_SUFFIX']).'.LOCK';
1195 
1196  // Wird keine lock_msg gesetzt, wird über get_backtrace() der letzte Aufruf ermittelt.
1197  if (empty($lock_msg)) {
1198  $lock_msg = get_backtrace();
1199  }
1200 
1201  // Lock verfällt per default nach einer Stunde
1202  if ($expiry_date == 0) {
1203  $expiry_date = time()+60*60;
1204  } else {
1205  $expiry_date += time();
1206  }
1207 
1208  $lock_content = array_merge(self::getDefaultCronLock($expiry_date), [
1209  'lock_msg' => $lock_msg
1210  ]);
1211 
1212  /*
1213  * Wenn Lock nicht vorhanden, expiry_date schreiben. Wenn doch
1214  * prüfen ob Lock bereits abgelaufen ist.
1215  */
1216  if (!Ego_System::file_exists($lock_file)) {
1217  self::file_put_contents($lock_file, json_encode($lock_content, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));
1218  } else {
1219  $lock_content = array_merge($lock_content, json_decode(self::file_get_contents($lock_file), true) ?? []);
1220  $lock_time = strtotime($lock_content['expiry_date']);
1221 
1222  // Falls der Prozess, der die CRON.LOCK Datei erzeugt hat, nicht mehr existiert, wird die CRON.LOCK sofort gelöscht
1223  if (!empty($lock_content['pid']) && function_exists('posix_getsid') && @posix_getsid($lock_content['pid']) === false) {
1225  self::setCronLock($original_expiry_date, $original_lock_msg);
1226  return;
1227  }
1228 
1229  if ($lock_time > time()) {
1230  $msg = "Neuer Lock konnte nicht gesetzt werden, da bereits ein Lock seit ".date("d.m.Y \u\m H:i:s", strtotime($lock_content['start_date']))." existiert.";
1231  $msg.= "<br/>Dieser verfällt am ".date("d.m.Y \u\m H:i:s", $lock_time).".";
1232  $msg.= "<p>".$lock_msg."</p>";
1233 
1234  throw new Exception($msg);
1235  } else {
1236  self::file_put_contents($lock_file, json_encode($lock_content, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE));
1237  }
1238  }
1239  }
1240 
1247  private static function getDefaultCronLock($expiry_date) {
1248  return [
1249  'pid' => @getmypid(),
1250  'start_date' => date('Y-m-d H:i:s'),
1251  'expiry_date' => date('Y-m-d H:i:s', $expiry_date)
1252  ];
1253  }
1254 
1260  public static function removeCronLock() {
1261  $lock_file = $GLOBALS['egotec_conf']['log_dir'].'CRON'.((string)$GLOBALS['__CRON_LOCK_SUFFIX']).'.LOCK';
1262 
1263  if (self::file_exists($lock_file)) {
1264  @unlink($lock_file);
1265  }
1266  }
1267 
1273  public static function readCronLock($cron_variable) {
1274  $lock_file = $GLOBALS['egotec_conf']['log_dir'].'CRON'.((string)$GLOBALS['__CRON_LOCK_SUFFIX']).'.LOCK';
1275 
1276  if (!self::file_exists($lock_file)) {
1277  return null;
1278  }
1279 
1280  $fp = fopen($lock_file, "a+");
1281 
1282  $count = 0;
1283  $timeout_secs = 10; //number of seconds of timeout
1284  $got_lock = true;
1285  while (!flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
1286  if ($wouldblock && $count++ < $timeout_secs) {
1287  sleep(1);
1288  } else {
1289  $got_lock = false;
1290  break;
1291  }
1292  }
1293 
1294  flock($fp, LOCK_UN);
1295  fclose($fp);
1296 
1297  if ($got_lock) {
1298  $lock_content = json_decode(self::file_get_contents($lock_file), true);
1299 
1300  // Falls die Datei abgelaufen ist, wird kein Wert zurückgeliefert
1301  if (!isset($lock_content['expiry_date']) || strtotime($lock_content['expiry_date']) < time()) {
1302  return null;
1303  }
1304 
1305  return $lock_content[$cron_variable];
1306  }
1307 
1308  return null;
1309  }
1310 
1316  public static function addCronLock($cron_variable, $value, $expiry_date = 0) {
1317  $lock_file = $GLOBALS['egotec_conf']['log_dir'].'CRON'.((string)$GLOBALS['__CRON_LOCK_SUFFIX']).'.LOCK';
1318  $fp = fopen($lock_file, "a+");
1319 
1320  $count = 0;
1321  $timeout_secs = 10; //number of seconds of timeout
1322  $got_lock = true;
1323  while (!flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
1324  if ($wouldblock && $count++ < $timeout_secs) {
1325  sleep(1);
1326  } else {
1327  $got_lock = false;
1328  break;
1329  }
1330  }
1331 
1332  flock($fp, LOCK_UN);
1333  fclose($fp);
1334 
1335  if ($got_lock) {
1336  $lock_content = json_decode(self::file_get_contents($lock_file), true);
1337  $lock_content[$cron_variable] = $value;
1338 
1339  // Das Ablaufdatum muss immer gesetzt sein; auch wenn die Datei über "addCronLock" neu angelegt wird
1340  if (!isset($lock_content['expiry_date'])) {
1341  if ($expiry_date == 0) {
1342  $expiry_date = time()+60*60;
1343  } else {
1344  $expiry_date += time();
1345  }
1346  $lock_content = array_merge($lock_content, self::getDefaultCronLock($expiry_date));
1347  }
1348 
1349  // Die Sperr-Nachricht sollte ebenfalls immer gesetzt sein
1350  if (!isset($lock_content['lock_msg'])) {
1351  $lock_content['lock_msg'] = get_backtrace();
1352  }
1353 
1354  self::file_put_contents($lock_file, json_encode($lock_content, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
1355  }
1356  }
1357 
1363  public static function cronLockExists() {
1364  $lock_file = $GLOBALS['egotec_conf']['log_dir'].'CRON'.((string)$GLOBALS['__CRON_LOCK_SUFFIX']).'.LOCK';
1365  if (self::file_exists($lock_file)) {
1366  $fp = fopen($lock_file, "r");
1367 
1368  $count = 0;
1369  $timeout_secs = 10; //number of seconds of timeout
1370  $got_lock = true;
1371  while (!flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) {
1372  if ($wouldblock && $count++ < $timeout_secs) {
1373  sleep(1);
1374  } else {
1375  $got_lock = false;
1376  break;
1377  }
1378  }
1379 
1380  flock($fp, LOCK_UN);
1381  fclose($fp);
1382 
1383  if ($got_lock) {
1384  $lock_content = json_decode(self::file_get_contents($lock_file), true);
1385  if (!isset($lock_content['expiry_date']) || strtotime($lock_content['expiry_date']) < time()) {
1386  return false;
1387  }
1388  return true;
1389  }
1390  }
1391  return false;
1392  }
1393 
1400  public static function checkCron0($site) {
1401  require_once 'cron/Ego_Cron.php';
1402  $cron = new Ego_Cron();
1403  $cron0_error = true;
1404 
1405  $list = array(
1406  'hourly' => array('title' => $GLOBALS['auth']->translate('stündlich'), 'interval' => 60 * 60),
1407  'daily' => array('title' => $GLOBALS['auth']->translate('täglich'), 'interval' => 60 * 60 * 24),
1408  'weekly' => array('title' => $GLOBALS['auth']->translate('wöchentlich'), 'interval' => 60 * 60 * 24 * 7),
1409  'monthly' => array('title' => $GLOBALS['auth']->translate('monatlich'), 'interval' => 60 * 60 * 24 * 31)
1410  );
1411 
1412  // Die letzten Ausführungszeiten aller System CRON Funktionen
1413  $system_cron = array();
1414  $system_cron_exists = false;
1415  if (($file = $GLOBALS['egotec_conf']['log_dir'] . 'cron.system') && self::file_exists($file)) {
1416  $system_cron = @unserialize(self::file_get_contents($file));
1417  if (!is_array($system_cron)) {
1418  $system_cron = array();
1419  } else {
1420  $system_cron_exists = true;
1421  }
1422  }
1423 
1424  foreach ($cron->crons as $cron_data) {
1425  if (in_array($cron_data['section'], array_keys($list))) {
1426  // Nur Aktionen auflisten, die mit der Lizenz und Konfiguration ausgeführt werden
1427  $skip_cron = false;
1428  switch ($cron_data['function']) {
1429  case 'cron_update_urls':
1430  case 'cron_clean_urls':
1431  // Nur wenn Rewrite2 verwendet wird
1432  $skip_cron = $GLOBALS['egotec_conf']['rewrite_engine'] != 'url';
1433  break;
1434  case 'glossary_to_xml':
1435  // Nur wenn der Seitentyp Glossar aktiviert ist
1436  $skip_cron = !$site->admin['enabled_types']['glossary'];
1437  break;
1438  case 'cron_kfz_abrechnung':
1439  // Nur wenn der Seitentyp Kfz-Verwaltung aktiviert ist
1440  $skip_cron = !($site->admin['enabled_types']['kfz_management']
1441  && self::checkLicence($GLOBALS['egotec_conf']['lib_dir'] . 'type/site/kfz_management'));
1442  break;
1443  case 'cron_media_office_index':
1444  // Nur wenn die Office Indizierung aktiviert ist
1445  $skip_cron = !(!$GLOBALS['egotec_conf']['liveserver']
1446  && $site->site['type'] == 'media'
1447  && $GLOBALS['egotec_conf']['openoffice']['active']
1448  && self::checkLicence($GLOBALS['egotec_conf']['lib_dir'] . 'type/site/search+'));
1449  break;
1450  case 'update_piwik_sites':
1451  case 'import_piwik_logs':
1452  // Nur wenn Piwik eingestellt ist
1453  $skip_cron = !self::isStatistic(($GLOBALS['site']->admin['piwik']['auth_token'] ?: $GLOBALS['egotec_conf']['piwik']['auth_token']));
1454  break;
1455  case 'cron_escalation':
1456  // Nur wenn Workflows aktiviert sind
1457  $skip_cron = !($site->admin['workflow']['enabled']
1458  && self::checkLicence($GLOBALS['egotec_conf']['lib_dir'] . 'workflow'));
1459  }
1460  if ($skip_cron) {
1461  continue;
1462  }
1463 
1464  // Letzte Ausführzeit dieser Funktion ermitteln
1465  if ($system_cron_exists) {
1466  if (isset($system_cron[$cron_data['function']])) {
1467  $cron_data['last_exec'] = $system_cron[$cron_data['function']];
1468  $cron_data['error'] = $cron_data['last_exec'] < (time() - $list[$cron_data['section']]['interval']);
1469  if ($cron_data['error']) {
1470  $list[$cron_data['section']]['error'] = true;
1471  }
1472  } else {
1473  $cron_data['warning'] = true;
1474  }
1475  }
1476 
1477  $list[$cron_data['section']]['crons'][] = $cron_data;
1478  }
1479  }
1480 
1481  // Die letzten Ausführungszeiten ermitteln
1482  foreach (array_keys($list) as $interval) {
1483  $file = $GLOBALS['egotec_conf']['log_dir'] . "cron.{$interval}";
1484  if (self::file_exists($file)) {
1485  $list[$interval]['date'] = self::file_get_contents($file);
1486  if ($list[$interval]['date'] >= (time() - $list[$interval]['interval'])) {
1487  $cron0_error = false;
1488  } else {
1489  $list[$interval]['error'] = true;
1490  }
1491  }
1492  }
1493 
1494  return [
1495  'error' => $cron0_error,
1496  'list' => $list
1497  ];
1498  }
1499 
1506  public static function file_exists($file)
1507  {
1508  if (!$GLOBALS['egotec_conf']['noclearstatcache']) {
1509  clearstatcache();
1510  }
1511  return file_exists($file);
1512  }
1513 
1533  public static function parseCsvLine($str, $delimiter=';', $qualifier='"', $qualifierEscape = '\\')
1534  {
1535  $fields = array();
1536  while (strlen($str) > 0)
1537  {
1538  if ($str[0] == $delimiter)
1539  $str = substr($str, 1);
1540  if ($str[0] == $qualifier)
1541  {
1542  $value = '';
1543  for ($i = 1; $i < strlen($str); $i++)
1544  {
1545  if (($str[$i] == $qualifier) && ($str[$i-1] != $qualifierEscape))
1546  {
1547  $str = substr($str, (strlen($value) + 2));
1548  $value = str_replace(($qualifierEscape.$qualifier), $qualifier, $value);
1549  break;
1550  }
1551  $value .= $str[$i];
1552  }
1553  } else
1554  {
1555  $end = strpos($str, $delimiter);
1556  $value = ($end !== false) ? substr($str, 0, $end) : $str;
1557  $str = substr($str, strlen($value));
1558  }
1559  $fields[] = $value;
1560  }
1561 
1562  return $fields;
1563  }
1564 
1570  public static function isWindows()
1571  {
1572  return $_SERVER['WINDIR'] || $_SERVER['windir'] || $_ENV['WINDIR'] || $_ENV['windir'] || getenv('windir');
1573  }
1574 
1581  public static function commandExists($cmd) {
1582  $format = self::isWindows() ? "where %s" : "command -v %s";
1583  $parts = explode(' ', sprintf($format, $cmd));
1584  $return = self::exec($parts[0], array($parts[1], $parts[2]));
1585  return !empty($return);
1586  }
1587 
1593  public static function getFileDescriptorUsage() : float {
1594  $fd_size = 0;
1595  foreach (['/proc/self/fd', '/dev/fd'] as $path) {
1596  self::exec('touch', [$path], $output, $return, false);
1597  if ($return == 0) {
1598  self::exec('ls', [$path, '|', 'wc', '-l'], $output, $return, false);
1599  if ($return === 0 && ($n = (int) $output[0]) > $fd_size) {
1600  $fd_size = $n;
1601  }
1602  }
1603  }
1604  return $fd_size / PHP_FD_SETSIZE;
1605  }
1606 
1614  public static function encode_path($url, $id=0)
1615  {
1616  if ($_SESSION['export'])
1617  {
1618  mb_regex_encoding('UTF-8');
1619  $return = mb_eregi_replace("[^[a-zA-Z0-9]]","_", $url);
1620  } else
1621  {
1622  $return = strtr($url, "%\n\r\t,;#-+?:&/'\".\\", '_________________');
1623  }
1624  if ($id && $url!=$return)
1625  {
1626  $return.= '-p-'.$id;
1627  }
1628  return urlencode($return);
1629  }
1630 
1637  public static function decode_path( $url )
1638  {
1639  //$url = iconv('US-ASCII//TRANSLIT', 'UTF-8', $url);
1640  return $url;
1641  }
1642 
1648  public static function clearPageLocks()
1649  {
1650  $db = new_db_connection();
1651  $db->delete(array(
1652  'table' => 'egotec_page_lock',
1653  'where' => "1=1"
1654  ));
1655 
1656  }
1657 
1665  public static function parseIniFile($file) {
1666  $lines = file($file);
1667  $array = array();
1668  foreach ($lines as $entry) {
1669  if (strpos($entry, ';') !== 0) {
1670  $content = explode('=', $entry, 2);
1671  $array[rtrim($content[0])] = trim($content[1]);
1672  }
1673  }
1674  return $array;
1675  }
1676 
1684  public static function isEmptyContent($str)
1685  {
1686  if ($GLOBALS['frontend_admin']) {
1687  // In der Frontend Administration die automatisch generierten HTML Tags entfernen
1688  $str = preg_replace('/<([^ ]+) [^>]*data-edit-type="[^"]+"[^>]*>(.*?)<\/\\1>/msi', '$2', $str);
1689  }
1690  $str = strip_tags($str, '<img><div><input><textarea><form><hr><param><object><video><iframe><embed>');
1691  $str = html_entity_decode($str);
1692  $str = str_replace(
1693  array(
1694  '',
1695  ' ',
1696  "\n",
1697  "\r",
1698  chr(160) // nbsp
1699  ),
1700  '',$str
1701  );
1702  if (strlen($str) == 0)
1703  {
1704  return true;
1705  } else
1706  {
1707  return false;
1708  }
1709  }
1710 
1725  public static function urltopage($url, $params=array(), $only_site = false, $error_page = false, $commit_params = false)
1726  {
1727  require_once ('base/Site.php');
1728  $url = preg_replace('/#.*?$/ims', '', $url); // URL ohne Anker verwenden
1729 
1730  try
1731  {
1732  // keine Sprechende URL
1733  if (strpos($url, 'index.php?') !== false || strpos($url, 'admin.php?') !== false)
1734  {
1735  return self::_urltopage_index($url, $params);
1736  } else
1737  { // eine Sprechende URL
1738  // Mediapool Anteil entfernen
1739  $url = preg_replace('/\/_\/.*?$/ims', '.html', $url);
1740  return self::_urltopage_sprechend($url, $only_site, $error_page, $commit_params, $params);
1741  }
1742  }
1743  catch (Exception $e)
1744  {
1745  return false;
1746  }
1747  }
1748 
1749  private static function _urltopage_sprechend($url, $only_site, $error_page, $commit_params, $params)
1750  {
1751  if ($GLOBALS['egotec_conf']['rewrite_engine'] == 'url') {
1752  // Die URL in der Datenbank suchen
1753  $info = Ego_System::parseUrl($url);
1754  $domain = $info['host'] ?? $_SERVER['HTTP_HOST'];
1755  $file = ($pos = strpos($info['datei'], '.')) ? substr($info['datei'], 0, $pos) : $info['datei'];
1756  $dir = ltrim($info['pfad'] . '/' . $file, '/');
1757 
1758  if (strpos($dir, '%') !== false) {
1759  // Ggf. muss der Wert vorher noch dekodiert werden
1760  $dir = urldecode(str_replace('+', '%2B', $dir));
1761  }
1762 
1763  $db = new_db_connection(array(
1764  'table' => 'egotec_url',
1765  'where' => "domain = :domain AND dir = :dir",
1766  'bind' => array(
1767  'domain' => $domain,
1768  'dir' => $dir
1769  )
1770  ));
1771  if ($db->nextRecord()) {
1773  'site' => $db->Record['site'],
1774  'lang' => $db->Record['lang'],
1775  'id' => $db->Record['id']
1776  ]), $params['params']['param']);
1777  }
1778  return null;
1779  }
1780 
1781  if ($commit_params)
1782  {
1783  global $dir;
1784  }
1785 
1786  $req = array();
1787 
1788  // HTTP Host rausnehmen
1789  if (preg_match("#^http[s]?://([^/]+)#i", $url, $m))
1790  {
1791  $http_host = $m[1];
1792  $url = substr($url, strlen($m[0]));
1793  }
1794 
1795  $pos = strpos($url, $GLOBALS['egotec_conf']['url_dir']);
1796  if ($pos === 0)
1797  {
1798  $url = substr($url, strlen($GLOBALS['egotec_conf']['url_dir']));
1799  }
1800 
1801  // Die Dateiendung aus der URL entfernen
1802  $dot_pos = strrpos($url, '.');
1803  if ($dot_pos!==false)
1804  { // Dateiendung bestimmen.
1805  $request_suffix = substr($url, $dot_pos);
1806  $url = substr($url, 0, $dot_pos);
1807  } else
1808  {
1809  $request_suffix = '.html';
1810  }
1811 
1812  /*
1813  * 1. Schritt - Site Lang und Skin rauskriegen
1814  */
1815 
1816  $dir = dirname($url);
1817  if ($dir && $dir!='.')
1818  { // Den Pfad entschlüsseln. Site, Skin, Lang bestimmen
1819  $dir = explode('/', $dir);
1820  if ($dir && Ego_System::file_exists($GLOBALS['egotec_conf']['site_dir'].$dir[0]))
1821  { // Site aus Pfad gewinnen.
1822  $req['site'] = array_shift($dir);
1823  $url = substr($url, strlen($req['site'])+1);
1824  }
1825  if ($dir && strlen($dir[0])==2)
1826  { // Die Sprache aus dem Pfad gewinnen.
1827  $req['lang'] = array_shift($dir);
1828  $url = substr($url, 3);
1829  }
1830  if ($dir && Ego_System::file_exists($GLOBALS['egotec_conf']['skin_dir'].$dir[0]))
1831  { // Skin aus Pfad gewinnen.
1832  $req['skin'] = array_shift($dir);
1833  $url = substr($url, strlen($req['skin'])+1);
1834  }
1835 
1836  $meta_url = $url; // Die URL OHNE site, skin und lang
1837 
1838  // Den Pfad berücksichtigen
1839  $path_index = 0;
1840  $num_path = 0;
1841  while ($dir[$path_index])
1842  {
1843  $num_path+= strlen($dir[$path_index])+1;
1844  $path_index++;
1845  }
1846  $url = ltrim(substr($url, $num_path),'/');
1847  }
1848 
1849  $url = explode('-', $url); // %09
1850  do
1851  {
1852  $key = urldecode(next($url));
1853  $value = str_replace('%2d', '-', urldecode(next($url)));
1854  $req[$key] = urldecode($value);
1855  } while ($key);
1856 
1858  if ($http_host && Ego_System::file_exists($GLOBALS['egotec_conf']['bin_dir'].'admin/popup_virtual_hosts.php'))
1859  {
1860  $virtual_hosts = self::getVirtualHosts();
1861  if (!$req['site'])
1862  {
1863  $http_host = strtolower($http_host);
1864 
1865  if (!isset($virtual_hosts[$http_host]))
1866  {
1867  if ($http_host != $_SERVER['HTTP_HOST']) {
1868  /* Wenn es einen Host gibt, der nicht der aktuelle Host ist und es keinen virtuellen Host gibt,
1869  * handelt es sich wohlmöglich um eine externe URL, die nicht aufgelöst werden soll. */
1870  return false;
1871  }
1872  $req['site'] = $GLOBALS['egotec_conf']['default_site'];
1873  } else {
1874  $req['site'] = $virtual_hosts[$http_host]['site'];
1875  $GLOBALS['egotec_conf']['default_site'] = $req['site'];
1876  }
1877  if (!$req['lang'] && $virtual_hosts[$http_host]['lang'])
1878  {
1879  $req['lang'] = $virtual_hosts[$http_host]['lang'];
1880  }
1881  } else {
1882  if (isset($virtual_hosts[$http_host]))
1883  {
1884  $GLOBALS['egotec_conf']['default_site'] = $virtual_hosts[$http_host];
1885  }
1886  }
1887  }
1888 
1889  if (!$req['site'])
1890  {
1891  $req['site'] = $GLOBALS['egotec_conf']['default_site'];
1892  }
1893  try {
1894  $site = new Site($req['site'], $req['lang'], $req['skin']);
1895  } catch (Exception $e) {
1896  switch ($e->getCode()) {
1898  array_unshift($url, $req['lang']);
1899  unset($req['lang']);
1900  $site = new Site($req['site'], '', $req['skin']);
1901  break;
1902  default:
1903  if ($error_page)
1904  {
1905  $req['site'] = $GLOBALS['egotec_conf']['default_site'];
1906  $site = new Site($GLOBALS['egotec_conf']['default_site']);
1907  if ($commit_params)
1908  {
1909  self::header(404);
1910  }
1911  $req['p'] = $site->site['error_id']?$site->site['error_id']:$site->rootId;
1912  } else
1913  {
1914  return false; // Site+Lang gibts nicht
1915  }
1916  }
1917  }
1918 
1919  if ($req['lang'])
1920  {
1921  try {
1922  $site->setLanguage($req['lang']);
1923  } catch (Site_Exception $exception)
1924  { // Falls die Sprache nicht existiert
1925  if ($error_page)
1926  {
1927  unset($name);
1928  unset($req['lang']);
1929  switch ($exception->getCode())
1930  {
1932  $site = new Site(
1933  $req['site'],
1934  '',
1935  $req['skin'],
1936  !$req['nonactive']
1937  );
1938  break;
1940  $site = new Site();
1941  break;
1942  }
1943  $req['id'] = $site->site['error_id'];
1944  } else
1945  {
1946  return false;
1947  }
1948  }
1949  }
1950 
1951  if ($only_site)
1952  {
1953  if ($commit_params)
1954  {
1955  foreach ($req as $k => $v)
1956  {
1957  $_REQUEST[$k] = $v;
1958  }
1959  }
1960  return $site;
1961  }
1962 
1963  /*
1964  * 2. Schritt - Die Page aus der ID oder aus dem Namen erzeugen
1965  */
1966 
1967  $req['id'] = $req['p']; // id sollte aus Gründen der Suchmaschinenoptimierung nicht in der URL vorkommen
1968  if ($req['id'] && !is_numeric($req['id']))
1969  {
1970  if ($error_page)
1971  {
1972  $req['id'] = $site->site['error_id'];
1973  } else
1974  {
1975  return false;
1976  }
1977  }
1978 
1979  $name = urldecode($url[0]);
1980  $lang_name = ($req['lang']?$req['lang'].'/':'').$meta_url;
1981  if (!$meta_url && !$name && !$req['id'])
1982  { // Die Startseite wird gewünscht
1983  $req['id'] = $site->rootId;
1984  }
1985 
1986  $current_path = array();
1987  if (!$req['id'])
1988  { // Wenn die Seitenid nicht explizit gesetzt ist, dann muss sie aus dem Namen gewonnen werden.
1989  if (!$meta_url)
1990  { // Auf die URL prüfen.
1991  $meta_url = $name;
1992  }
1993  if (!$meta_url)
1994  {
1995  $req['id'] = $site->rootId;
1996  } else {
1997  $pages = $site->getPages(array('where' => 'url=\''.$meta_url.'\''), array('auth_or' => '1=1', 'inactive' => true));
1998  if ($pages && $pages->numRecords() == 1)
1999  {
2000  $page = $pages->nextPage();
2001  $current_path = $page->getPath(false, array(), false);
2002  } else { // Über das URL-Feld wurde kein passenden Eintrag gefunden
2003  $parent = false;
2004  if (is_array($dir))
2005  {
2006  foreach($dir as $path_name)
2007  {
2008  $path_name = urldecode($path_name);
2009  if (strpos($path_name, '-')!==false)
2010  {
2011  $path_name = explode('-', $path_name);
2012  $parent = $site->getPage((int)$path_name[2], array('auth_or' => '1=1', 'inactive' => true));
2013  } else {
2014  if (!is_object($parent))
2015  {
2016  $pages = $site->getRoot(array('auth_or' => '1=1'))->getChildren(
2017  array('where' => 'name=:name OR name LIKE :name', 'bind' => array('name' => $path_name)),
2018  array('auth_or' => '1=1', 'inactive' => true)
2019  );
2020  $parent = $pages->nextPage();
2021  } else {
2022  $pages = $parent->getChildren(
2023  array('where' => 'name=:name OR name LIKE :name', 'bind' => array('name' => $path_name)),
2024  array('auth_or' => '1=1', 'inactive' => true)
2025  );
2026  $parent = $pages->nextPage();
2027  }
2028  }
2029  if (is_object($parent)) // Bei fehlerhaften Pfaden, die z.B. von Robots oder Würmern erzeugt werden, kann es vorkommen,
2030  { // dass keine Seite für ein Verzeichnis existiert.
2031  $current_path[] = $parent->field['id'];
2032  }
2033  }
2034  }
2035 
2036  if (!is_object($parent))
2037  {
2038  $parent = $site->getRoot(array('auth_or' => '1=1', 'inactive' => true));
2039  }
2040  }}
2041 
2042  if ($name)
2043  {
2044  if (is_object($page))
2045  { // Es wurde bereits eine passende Seite gefunden
2046  $req['id'] = $page->field['id'];
2047  } else
2048  {//Bisher konnte nur der Pfad generiert werden
2049  if (is_object($parent))
2050  {
2051  $pages = $parent->getChildren(
2052  array('where' => 'url=\''.$name.'\' OR name=\''.$name.'\' OR name like \''.$name.'\''),
2053  array('auth_or' => '1=1')
2054  );
2055  if (!$pages->numRecords())
2056  {
2057  $pages = $site->getPages(
2058  array('where' => 'url LIKE \''.$name.'\' OR name=\''.$name.'\' OR name like \''.$name.'\''),
2059  array('auth_or' => '1=1')
2060  );
2061  }
2062  } else {
2063  $pages = $site->getPages(
2064  array('where' => 'url LIKE \''.$name.'\' OR name=\''.$name.'\' OR name like \''.$name.'\''),
2065  array('auth_or' => '1=1')
2066  );
2067  }
2068  $req['id'] = $pages->nextPage()->field['id'];
2069  }
2070  if (!$req['id'] && $commit_params)
2071  {
2072  $GLOBALS['no_cache'] = true;
2073  }
2074  } else if (!$req['id'])
2075  { // Hier muss nochmals abgefragt werden, da z.B. bei einem Fehler, z.B. eine nicht vorhandene Sprache, die id gesetzt wird.
2076  $req['id'] = $site->rootId;
2077  }
2078  }
2079  if ($commit_params)
2080  {
2081  $GLOBALS['current_path'] = $current_path;
2082  foreach ($req as $k => $v)
2083  {
2084  $_REQUEST[$k] = $v;
2085  }
2086  }
2087  $get_page_param = array();
2088  $get_page_param['auth_or'] = '1=1';
2089  $get_page_param['inactive'] = true;
2090  return $site->getPage($req['id'], $get_page_param);
2091  }
2092 
2093  private static function _urltopage_index($url, $params=array())
2094  {
2095  // ID ermitteln
2096  $pattern = '/id=(\d+)/';
2097  preg_match($pattern, $url, $match);
2098  $id = $match[1];
2099 
2100  // Site ermitteln
2101  if(!$params['site'])
2102  {
2103  $pattern = '/site=([^\?&]+)/';
2104  preg_match($pattern, $url, $match);
2105  $site_id = $match[1];
2106  }
2107  else
2108  {
2109  $site_id = $params['site'];
2110  }
2111 
2112  // Sprache ermitteln
2113  if(!$params['lang'])
2114  {
2115  $pattern = '/lang=([a-z]+)/';
2116  preg_match($pattern, $url, $match);
2117  $site_lang = $match[1];
2118  }
2119  else
2120  {
2121  $site_lang = $params['lang'];
2122  }
2123 
2124  $site = new Site($site_id, $site_lang);
2125  if (empty($GLOBALS['site'])) {
2126  // Wird eine Page ermittelt, muss global immer eine Site existieren (für PageExtension)
2127  $GLOBALS['site'] = $site;
2128  }
2129  $page = $site->getPage($id, $params['params']['param']);
2130 
2131  return $page;
2132  }
2133 
2149  public static function copy($src, $dest, $except = '', $useLinks = false, $noArchive = false, $preserveDate = false) {
2150  set_time_limit(0);
2151 
2152  if (is_dir($src)) {
2153  Ego_System::mkdir($dest);
2154  $dir = dir($src);
2155 
2156  while (($entry = $dir->read()) !== false) {
2157  if ($entry == '.svn' || $entry == '.' || $entry == '..') {
2158  continue;
2159  }
2160 
2161  if (!empty($except) && preg_match($except, $entry)) {
2162  continue;
2163  }
2164 
2165  // Keine Archiv Einträge übernehmen
2166  if (
2167  $noArchive
2168  && (
2169  preg_match('/\d+?_.+?/', $entry)
2170  || (
2171  preg_match('/pool\/\d+?$/', $src)
2172  && preg_match('/\d+/', $entry)
2173  )
2174  )
2175  ) {
2176  continue;
2177  }
2178 
2179  $path = $src.'/'.$entry;
2180  self::copy($path, $dest.'/'.$entry, $except, $useLinks, $noArchive, $preserveDate);
2181  }
2182 
2183  $dir->close();
2184  } elseif (empty($except) || !preg_match($except, basename($src))) {
2185  // falls gewünscht einen Hard Link setzen
2186  if ($useLinks && @link($src, $dest)) {
2187  return true;
2188  }
2189 
2190  $result = @copy($src, $dest);
2191 
2192  // Änderungsdatum nicht ändern
2193  if ($result && $preserveDate && ($dt = filemtime($src)) !== false) {
2194  @touch($dest, $dt);
2195  }
2196  return $result;
2197  }
2198 
2199  return true;
2200  }
2201 
2211  public static function move($src, $dest) {
2212  set_time_limit(0);
2213  Ego_System::mkdir(dirname($dest));
2214  return @rename($src, $dest);
2215  }
2216 
2226  public static function getAllSites($username = '', $perm = '', $table = false, $type = '')
2227  {
2228  require_once 'base/Site.php';
2229 
2230  $types = array_filter(array_map('trim', explode(',', $type)));
2231 
2232  $unique_key = md5(serialize([$username, $perm, $table, $types]));
2233  if (!empty(self::$allSites[$unique_key])) {
2234  return self::$allSites[$unique_key];
2235  }
2236  if ($username)
2237  {
2238  $db = new_db_connection(array(
2239  'fields' => 'user_id',
2240  'table' => 'egotec_user',
2241  'where' => 'username=:username',
2242  'bind' => array('username' => $username)
2243  ));
2244  if (!$db->nextRecord())
2245  {
2246  return array(); // Bei einem nicht vorhandenen Benutzer werden keine Mandanten zurückgegeben.
2247  }
2248  $user_id = $db->Record['user_id'];
2249  } else {
2250  $user_id = false;
2251  }
2252  $dir = opendir($GLOBALS['egotec_conf']['site_dir']);
2253  $sites = $sort = array();
2254  while ($file = readdir($dir))
2255  {
2256  if (
2257  is_dir($GLOBALS['egotec_conf']['site_dir'].$file) && $file[0] != '.' &&
2258  Ego_System::file_exists($GLOBALS['egotec_conf']['site_dir'].$file.'/conf.ini')
2259  ) {
2260  $loop_site = new Site($file, '', '', !$GLOBALS['admin_area']);
2261 
2262  if (!empty($types) && !in_array($loop_site->site['type'], $types)) {
2263  continue;
2264  }
2265 
2266  // Prüfen ob dieser Mandant auch in der Datenbank existiert
2267  if ($table)
2268  {
2269  $db = new_db_connection();
2270  if (!$db->tableExists($loop_site->pageTable))
2271  {
2272  egotec_warning_log("Site table {$loop_site->pageTable} does not exist.");
2273  continue;
2274  }
2275  }
2276 
2277  if (
2278  !$user_id ||
2279  $loop_site->hasRight($perm, false, $user_id)
2280  ) {
2281  $sites[$file] = $loop_site;
2282  $sort[] = mb_strtolower($loop_site->site['title']);
2283  }
2284  }
2285  }
2286  closedir($dir);
2287 
2288  array_multisort($sort, SORT_ASC, SORT_NATURAL, $sites);
2289 
2290  self::$allSites[$unique_key] = $sites;
2291  return $sites;
2292  }
2293 
2299  public static function getAllSkins() {
2300  $skins = self::getSkins();
2301  foreach ($skins as $type => $list) {
2302  foreach ($list as $skin => $title) {
2303  if ($skin == '_empty') {
2304  unset($skins[$type][$skin]);
2305  continue;
2306  }
2307  $skins[$type][$skin] = array();
2308  }
2309  }
2310  foreach (Ego_System::getAllSites() as $site) {
2311  foreach (array_unique(array_merge(
2312  array($site->conf['site']['default_skin'], $site->conf['site']['mobile_skin']),
2313  explode(',', $site->conf['site']['skins'])
2314  )) as $skin) {
2315  if (
2316  !empty($skin)
2317  && isset($skins['skins'][$skin])
2318  && !in_array($site->name, $skins['skins'][$skin])
2319  ) {
2320  $skins['skins'][$skin][] = $site;
2321  }
2322  }
2323  if (
2324  $site->theme
2325  && (!$skins['themes'][$site->theme]
2326  || !in_array($site->name, $skins['themes'][$site->theme]))
2327  ) {
2328  $skins['themes'][$site->theme][] = $site;
2329  }
2330  }
2331  return $skins;
2332  }
2333 
2340  public static function getSkins($more_themes = array()) {
2341  $cache = self::getCache();
2342  $cache_key = 'getSkins' . md5(json_encode(func_get_args()));
2343  $result = $cache->get($cache_key);
2344 
2345  if ($result === null) {
2346  $result = array(
2347  'skins' => array(),
2348  'themes' => array()
2349  );
2350 
2351  // Alle Designs
2352  $skin_dir = $GLOBALS['egotec_conf']['skin_dir'];
2353  if (self::file_exists($skin_dir)) {
2354  $dir = dir($skin_dir);
2355  while ($file = $dir->read()) {
2356  if (
2357  is_dir($skin_dir.$file)
2358  && substr($file, 0, 1) != '.'
2359  && $file != 'base'
2360  && $file[0] != '_'
2361  ) {
2362  $result['skins'][$file] = $file;
2363  }
2364  }
2365  $dir->close();
2366  ksort($result['skins']);
2367  }
2368 
2369  // Alle Vorlagen
2370  $result['themes'] = array('_empty' => '--'); // keine Vorlage
2371  $theme_dir = $GLOBALS['egotec_conf']['egotec_dir'].'pub/theme/';
2372  if (self::file_exists($theme_dir)) {
2373  $dir = dir($theme_dir);
2374  while ($file = $dir->read()) {
2375  if(
2376  is_dir($theme_dir.$file)
2377  && substr($file, 0, 1) != '.'
2378  && $file != 'base'
2379  && $file[0] != '_'
2380  ) {
2381  $conf_file = $theme_dir.$file.'/conf.ini';
2382  if (Ego_System::file_exists($conf_file)) {
2383  $conf = parse_ini_file($conf_file);
2384  $title = $conf['title'];
2385  } else {
2386  $title = $file;
2387  }
2388  if (
2389  Ego_System::file_exists($theme_dir.$file.'/module.ini')
2390  || (
2391  Ego_System::file_exists($module_file = $GLOBALS['egotec_conf']['lib_dir'].$file.'/module.ini')
2392  && ($module_conf = parse_ini_file($module_file))
2393  && in_array("pub/theme/$file", explode(',', $module_conf['path']))
2394  )
2395  ) {
2396  $result['themes'][$file] = "[ $title ]";
2397  } else {
2398  $result['themes'][$file] = $title;
2399  }
2400  }
2401  }
2402  $dir->close();
2403  }
2404  foreach ($more_themes as $name => $theme) {
2405  if (!isset($result['themes'][$name])) {
2406  $result['themes'][$name] = $theme;
2407  }
2408  }
2409  ksort($result['themes']);
2410 
2411  $cache->set($cache_key, $result);
2412  }
2413 
2414  return $result;
2415  }
2416 
2426  public static function log($file, $message)
2427  {
2428  $file = $GLOBALS['egotec_conf']['log_dir'].$file;
2429  if (Ego_System::file_exists($file))
2430  {
2431  $size = filesize($file);
2432  if ($size > 100*1024*1024)
2433  { // größer als 100 MB
2434  $new_name = $file.'_'.date("Y-m-d_H-i-s");
2435  rename($file, $new_name);
2436  }
2437  }
2438  // Ist nicht mehr genug Speicherplatz vorhanden?
2439  $min = ($GLOBALS['egotec_conf']['log_min_disk_free']??10
2440  )*1024*1024; // MB -> Bytes, wenn nichts eingestellt min. 10 MB
2441  if (!is_dir($GLOBALS['egotec_conf']['log_dir'])) {
2442  self::mkdir($GLOBALS['egotec_conf']['log_dir']);
2443  }
2444  $bytes_free = disk_free_space($GLOBALS['egotec_conf']['log_dir']);
2445  if ($min > $bytes_free)
2446  { // zu wenig Speicherplatz
2447  // älteste Log löschen
2448  $times = array();
2449  $files = glob($file.'_*');
2450  foreach ($files as $f)
2451  {
2452  $m = array();
2453  if (
2454  strpos($f, $file)===0 &&
2455  preg_match('/_(\d{4}-\d{2}-\d{2})_(\d{2})-(\d{2})-(\d{2})$/', $f, $m)
2456  ) {
2457  $stamp = $m[1].' '.$m[2].':'.$m[3].':'.$m[4];
2458  $times[strtotime($stamp)] = $f;
2459  }
2460  }
2461  ksort($times);
2462  if (sizeof($times)>0)
2463  {
2464  unlink(current($times));
2465  } else
2466  {
2467  $last_mail_file = $GLOBALS['egotec_conf']['log_dir'].'disk_free_mail.date';
2468  $last_mail_date = '1970-01-01 00:00:00';
2469  if (Ego_System::file_exists($last_mail_file) && ($date = Ego_System::file_get_contents($last_mail_file))) {
2470  $last_mail_date = $date;
2471  }
2472  if (
2473  !$GLOBALS['egotec_conf']['no_disk_free_mail']
2474  && $last_mail_date + 3600 < date('Y-m-d H:i:s') // Nur einmal pro Stunde
2475  ) {
2476  Ego_System::file_put_contents($last_mail_file, date('Y-m-d H:i:s'));
2477  /*
2478  * problem - wenig Speicherplatz und keine alte Log Datei zum löschen
2479  * Benachrichtigung an den Admin
2480  */
2481  $frei = round($bytes_free / (1024*1024));
2482  $text = "Es ist nicht genügend Speicherplatz auf dem Server vorhanden.\n".
2483  "Aktuell sind auf dem Server $frei MB frei.\n\n".
2484  $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'];
2485  require_once('mail/Ego_Mail.php');
2486  $mail = new Ego_Mail();
2487  try {
2488  $mail->mail($GLOBALS['egotec_conf']['admin_mail'], 'Nicht genügend Speicherplatz auf dem Webserver', $text);
2489  } catch (Exception $e)
2490  {
2491  }
2492  }
2493 
2494  return; // keinen weiteren Log-Eintrag
2495  }
2496  }
2497 
2498  // endlich darf in die Log geschrieben werden
2499  error_log($message, 3, $file);
2500  }
2501 
2510  public static function checkRequirements()
2511  {
2512  $result = array(
2513  'passed' => true, // Prüfung bestanden oder nicht
2514  'installed' => array(), // Verfügbare Extensions
2515  'failed' => array(), // Fehlende Extensions
2516  'notice' => array() // Hinweise
2517  );
2518 
2519  /*
2520  * Voraussetzungen definieren
2521  *
2522  * Versionsangabe = diese Version muss mindestens installiert sein
2523  * true = Version ist egal, Extension wird aber benötigt
2524  * false = Version ist egal, Extension ist aber optional
2525  */
2526  $requirements = array(
2527  'php' => array(
2528  'min' => '7.4'
2529  ),
2530  'sys64' => array(
2531  'min' => 4
2532  ),
2533  'mysql' => array(
2534  'min' => '5.0'
2535  ),
2536  'oracle' => array(
2537  'min' => '10.2'
2538  ),
2539  'imagick' => array(
2540  'min' => true
2541  ),
2542  'fileinfo' => array(
2543  'min' => true
2544  ),
2545  'session' => array(
2546  'min' => true
2547  ),
2548  'sockets' => array(
2549  'min' => true
2550  ),
2551  'xml' => array(
2552  'min' => true
2553  ),
2554  'zlib' => array(
2555  'min' => true
2556  ),
2557  'soap' => array(
2558  'min' => true
2559  ),
2560  'pspell' => array(
2561  'min' => true
2562  ),
2563  'mbstring' => array(
2564  'min' => true
2565  ),
2566  'curl' => array(
2567  'min' => (bool) Ego_System::checkLicence($GLOBALS['egotec_conf']['lib_dir'].'lucene') || (bool) Ego_System::checkLicence($GLOBALS['egotec_conf']['lib_dir'].'elastic')
2568  )
2569  );
2570 
2571  // Alle geladenen Extensions
2572  $loaded_extensions = get_loaded_extensions();
2573 
2574  // Prüfung einleiten
2575  foreach($requirements as $requirement => $required)
2576  {
2577  $skip_version_compare = false;
2578  $installed = $failed = '';
2579 
2580  switch($requirement)
2581  {
2582  // PHP Version
2583  case 'php':
2584  $version = phpversion();
2585 
2586  $installed = "PHP {$required['min']} oder höher ist installiert ($version)";
2587  $failed = "PHP Version unzureichend ($version). Bitte aktualisieren Sie Ihre PHP Version auf {$required['min']} oder höher";
2588  break;
2589 
2590  // MySQL Version (nur falls vorhanden)
2591  case 'mysql':
2592  if(in_array(Ego_System::getDbDriver(), array('mysql', 'mysqli', 'innodb')))
2593  {
2594  $db = new_db_connection();
2595  $version = $db->getVersion();
2596 
2597  $installed = "MySQL {$required['min']} oder höher ist installiert ($version)";
2598  $failed = "MySQL Version unzureichend ($version). Bitte aktualisieren Sie Ihre MySQL Version auf {$required['min']} oder höher";
2599  } else
2600  {
2601  $installed = "MySQL wird nicht benötigt";
2602  }
2603  break;
2604 
2605  // Oracle Version (nur falls vorhanden)
2606  case 'oracle':
2607  if (Ego_System::getDbDriver() == 'oci')
2608  {
2609  if ($conn = @oci_connect($GLOBALS['egotec_conf']['db']['user'], $GLOBALS['egotec_conf']['db']['password'], $GLOBALS['egotec_conf']['db']['database'], 'AL32UTF8'))
2610  {
2611  $version = oci_server_version($conn);
2612  oci_close($conn);
2613 
2614  $installed = "Oracle {$required['min']} oder höher ist installiert ($version)";
2615  $failed = "Oracle Version unzureichend ($version). Bitte aktualisieren Sie Ihre Oracle Version auf {$required['min']} oder höher";
2616  }
2617  else
2618  {
2619  $version = false;
2620  $failed = "Oracle ist installiert, die Version konnte aber nicht ermittelt werden. Empfohlene Oracle Version ist {$required['min']} oder höher";
2621  }
2622  } else
2623  {
2624  $installed = "Oracle wird nicht benötigt";
2625  }
2626  break;
2627 
2628  // Mime Type erkennen
2629  case 'fileinfo':
2630  if (function_exists('finfo_file')) {
2631  $version = phpversion('fileinfo');
2632  $result['installed'][$requirement] = "Fileinfo ist installiert ($version)";
2633  } else {
2634  $result['failed'][$requirement] = "Fileinfo ist nicht installiert";
2635  }
2636  $skip_version_compare = true;
2637  break;
2638 
2639  // Test auf 64 Bit System
2640  case 'sys64':
2641  $installed = "64 Bit System";
2642  $failed = "32 Bit System";
2643  break;
2644 
2645  // Extensions bei denen die Versionierung egal ist
2646  default:
2647  $version = phpversion($requirement);
2648 
2649  /*
2650  * phpversion liefert false wenn die Extension nicht gefunden wurde,
2651  * aber auch wenn es nur keine Versionierung hierfür gibt. Deshalb nochmal prüfen
2652  */
2653  if (!$version)
2654  {
2655  $version = in_array($requirement, $loaded_extensions) ? '' : false;
2656  }
2657 
2658  if ($version === false)
2659  {
2660  $type = 'failed';
2661  if (!$required['min']) // falls Extension optional ist
2662  {
2663  $type = 'notice';
2664  }
2665 
2666  $result[$type][$requirement] = "$requirement ist nicht installiert";
2667  }
2668  else
2669  {
2670  $result['installed'][$requirement] = "$requirement ist installiert".($version != '' ? " ($version)" : '');
2671  }
2672 
2673  $skip_version_compare = true;
2674  break;
2675  }
2676 
2677  // Versionsüberprüfung überspringen
2678  if ($skip_version_compare)
2679  {
2680  continue;
2681  }
2682  if (
2683  $requirement == 'oracle'
2684  && preg_match('/\d+\.[^ ]*/', $version, $match)
2685  )
2686  {
2687  $version = $match[0];
2688  }
2689  // Versionen vergleichen
2690  if(!version_compare($version, $required['min'], '>=') && !$required['except'])
2691  {
2692  $result['failed'][$requirement] = $failed;
2693  }elseif(version_compare($version, $required['min'], '>=') && !$required['except'])
2694  {
2695  $result['installed'][$requirement] = $installed;
2696  }elseif(version_compare($version, $required['min'], '>=') && $required['except'])
2697  { //es gibt ausnahmen!!!
2698  $exceptions = explode(',', $required['except']);
2699 
2700  if (version_compare($version,$exceptions[0], '>=') && version_compare($version,$exceptions[1], '<'))
2701  {
2702  $result['failed'][$requirement] = $failed;
2703  }else
2704  {
2705  $result['installed'][$requirement] = $installed;
2706  }
2707  }else{
2708  $result['failed'][$requirement] = $failed;
2709  }
2710  }
2711 
2712  // MySQL oder Oracle müssen installiert sein
2713  if ($result['failed']['mysql'] && $result['failed']['oracle'])
2714  {
2715  $result['failed']['_db'] = "Weder MySQL noch Oracle sind installiert";
2716  }
2717 
2718  // GD oder ImageMagick müssen installiert sein
2719  if ($result['failed']['gd'] && $result['failed']['convert'])
2720  {
2721  $result['failed']['_image'] = "Weder GD noch ImageMagick sind installiert";
2722  }
2723 
2724  // Spezielle fehlgeschlagene Voraussetzungen als Hinweise markieren
2725  foreach($result['failed'] as $key => $value)
2726  {
2727  $set_notice = false;
2728 
2729  switch($key)
2730  {
2731  case 'mysql':
2732  if ($result['installed']['oracle'])
2733  {
2734  $set_notice = true;
2735  }
2736  break;
2737 
2738  case 'oracle':
2739  if ($result['installed']['mysql'])
2740  {
2741  $set_notice = true;
2742  }
2743  break;
2744 
2745  case 'gd':
2746  if ($result['installed']['convert'])
2747  {
2748  $set_notice = true;
2749  }
2750  break;
2751 
2752  case 'convert':
2753  if ($result['installed']['gd'])
2754  {
2755  $set_notice = true;
2756  }
2757  break;
2758  }
2759 
2760  if ($set_notice)
2761  {
2762  $result['notice'][$key] = $value;
2763  unset($result['failed'][$key]);
2764  }
2765  }
2766  // Systemvoraussetzungen werden nicht erfüllt
2767  if (sizeof($result['failed']) > 0)
2768  {
2769  $result['passed'] = false;
2770  }
2771 
2772  return $result;
2773  }
2774 
2781  public static function byte_format($byte)
2782  {
2783  if (is_numeric($byte)) {
2784  if ($byte > 1024*1024*1024) {
2785  return number_format($byte / (1024*1024*1024), 2).' GB';
2786  } elseif ($byte > 1024*1024) {
2787  return number_format($byte / (1024*1024), 2).' MB';
2788  } elseif ($byte > 1024) {
2789  return number_format($byte / (1024), 2).' kB';
2790  } else {
2791  return $byte.' B';
2792  }
2793  }
2794  return $byte;
2795  }
2796 
2806  public static function eternalCache($active, $clear = true)
2807  {
2808  if ($active)
2809  {
2810  self::file_put_contents($GLOBALS['egotec_conf']['cache_dir'].'eternal', time()+900); // Der Html Cache bleibt für 15' aktiv.
2811  } else {
2812  @unlink($GLOBALS['egotec_conf']['cache_dir'].'eternal');
2813 
2814  // Den gesamten Cache löschen
2815  if ($clear) {
2816  self::clearCacheAllSites();
2817  } else {
2818  // Den Nginx Cache immer löschen
2819  self::clearNginxCache();
2820  }
2821  }
2822  }
2823 
2829  public static function checkSSL()
2830  {
2831  try {
2832  return (bool) (self::file_get_contents('https://'.$_SERVER['HTTP_HOST'].$GLOBALS['egotec_conf']['url_dir']));
2833  } catch (Exception $e) {
2834  return false;
2835  }
2836  }
2837 
2844  public static function getDbDriver($db = null)
2845  {
2846  if (!$db) {
2847  $db = new_db_connection();
2848  }
2849  return substr(strrchr(get_class($db), '_'), 1);
2850  }
2851 
2858  public static function getMimeTypes($ext = '')
2859  {
2860  require_once('MIME/Type/Extension.php');
2861  $mime = new MIME_Type_Extension();
2862 
2863  $types = $mime->extensionToType;
2864 
2865  return ($ext ? $types[$ext] : $types);
2866  }
2867 
2875  public static function getFilePath($dir, $file)
2876  {
2877  $sub_dir = array(
2878  'site' => $GLOBALS['site']->name,
2879  'skin' => $GLOBALS['site']->skin
2880  );
2881 
2882  if (file_exists($GLOBALS['egotec_conf'][$dir.'_dir'].$sub_dir[$dir].'/'.$file))
2883  {
2884  return $GLOBALS['egotec_conf']['url_dir'].$dir.'/'.$sub_dir[$dir].'/'.$file;
2885  } elseif ($GLOBALS['site']->globalAllowed() && file_exists($GLOBALS['egotec_conf'][$dir.'_dir'].'_global/'.$file))
2886  {
2887  return $GLOBALS['egotec_conf']['url_dir'].$dir.'/_global/'.$file;
2888  } elseif (file_exists($GLOBALS['egotec_conf']['lib_dir'].'type/'.$dir.'/'.$file))
2889  {
2890  return $GLOBALS['egotec_conf']['url_dir'].'lib/'.$dir.'/'.$file;
2891  } else
2892  {
2893  return '';
2894  }
2895  }
2902  public static function getDirectorySize($pfad, &$links = array())
2903  {
2904  $totalsize = 0;
2905  $totalcount = 0;
2906  $dircount = 0;
2907  if ($handle = opendir ($pfad))
2908  {
2909  while (false !== ($file = readdir($handle)))
2910  {
2911  $nextpath = $pfad . '/' . $file;
2912  if ($file != '.' && $file != '..' && !is_link ($nextpath))
2913  {
2914  if (is_dir ($nextpath))
2915  {
2916  $dircount++;
2917  $result = Ego_System::getDirectorySize($nextpath, $links);
2918  $totalsize += $result['size'];
2919  $totalcount += $result['count'];
2920  $dircount += $result['dircount'];
2921  }elseif (is_file ($nextpath))
2922  {
2923  $stat = stat ($nextpath);
2924  if (!isset($links[$stat['ino']])) {
2925  $totalsize += $stat['size'];
2926  }
2927  if ($stat['nlink'] > 1) {
2928  $links[$stat['ino']] = $stat['nlink'];
2929  }
2930  $totalcount++;
2931  }
2932  }
2933  }
2934  }
2935  closedir ($handle);
2936  $total['size'] = $totalsize;
2937  $total['count'] = $totalcount;
2938  $total['dircount'] = $dircount;
2939  return $total;
2940  }
2941 
2951  public static function file_get_contents($filename, $utf8 = true, $context = null) {
2952  $host = $GLOBALS['egotec_conf']['proxy']['proxy_host'];
2953  $port = $GLOBALS['egotec_conf']['proxy']['proxy_port'];
2954  $ssl = $GLOBALS['egotec_conf']['proxy']['proxy_ssl'];
2955  $login = $GLOBALS['egotec_conf']['proxy']['proxy_login'];
2956  $password = $GLOBALS['egotec_conf']['proxy']['proxy_password'];
2957 
2958  if ($host && $port) {
2959  $options = array(
2960  'http' => array(
2961  'proxy' => ($ssl ? 'ssl://' : 'tcp://').$host.':'.$port,
2962  'request_fulluri' => true
2963  )
2964  );
2965  if ($login) {
2966  $auth = base64_encode($login . ":" . $password);
2967  $options['http']['header'] = "Proxy-Authorization: Basic $auth\r\n";
2968  }
2969  if ($context) {
2970  $options = array_merge_recursive(stream_context_get_options($context), $options);
2971  if (is_array($options['http']['header'])) {
2972  $options['http']['header'] = implode("\r\n", array_map('trim', $options['http']['header']));
2973  }
2974  }
2975  $context = stream_context_create($options);
2976  }
2977  $content = @file_get_contents($filename, false, $context);
2978  if ($context && $content === false) {
2979  // Im Fehlerfall ohne Context versuchen
2980  $content = @file_get_contents($filename);
2981  }
2982 
2983  // in UTF-8 kodieren
2984  if ($utf8 && $content) {
2985  return mb_convert_encoding($content, 'UTF-8', mb_detect_encoding($content, 'UTF-8, ISO-8859-1', true));
2986  } else {
2987  return $content;
2988  }
2989  }
2990 
3001  public static function file_put_contents($filename, $data, $flags = 0, $context = null) {
3002  @Ego_System::mkdir(dirname($filename));
3003  return file_put_contents($filename, $data, $flags, $context);
3004  }
3005 
3012  public static function filesize($file) {
3013  clearstatcache();
3014  return filesize($file);
3015  }
3016 
3022  public static function getCluster($site = null) {
3023  if (!Ego_System::checkLicence($GLOBALS['egotec_conf']['lib_dir'].'cluster')) {
3024  return array();
3025  }
3026  if (!$site) {
3027  $site = $GLOBALS['site'];
3028  }
3029 
3030  $count = range(1, self::MAX_CLUSTER);
3031  $cluster = array();
3032  foreach ($count as $c) {
3033  if (
3034  $site->admin['cluster']['cluster_'.$c.'_aktiv'] == 1
3035  && $site->admin['cluster']['cluster_'.$c.'_url'] != ''
3036  ) {
3037  $cluster[] = array(
3038  'url' => rtrim($site->admin['cluster']['cluster_'.$c.'_url'], '/') . '/',
3039  'id' => $c,
3040  'oneway' => (bool) $site->admin['cluster']['cluster_'.$c.'_oneway']
3041  );
3042  }
3043  }
3044  return $cluster;
3045  }
3046 
3057  public static function truncate($string, $length, $etc = '...', $break_words = false, $middle = false)
3058  {
3059  require_once('smarty/plugins/modifier.html_truncate.php');
3060  return smarty_modifier_html_truncate($string, $length, $etc, $break_words, $middle);
3061  }
3062 
3069  public static function getDesktopSite($site) {
3070  switch ($site->site['type']) {
3071  case 'content':
3072  $_SESSION['_last_desktop'] = array(
3073  'name' => $site->name,
3074  'language' => $site->language
3075  );
3076  break;
3077 
3078  case 'media':
3079  if (is_array($_SESSION['_last_desktop'])) {
3080  $_site = new Site(
3081  $_SESSION['_last_desktop']['name'],
3082  $_SESSION['_last_desktop']['language']
3083  );
3084  if ($_site->site['media'] == $site->name)
3085  {
3086  return $_site;
3087  }
3088  }
3089  foreach (Ego_System::getAllSites() as $_site) {
3090  if (
3091  $_site->site['media'] == $site->name
3092  && $_site->name != $site->name
3093  ) {
3094  return $_site;
3095  }
3096  }
3097  break;
3098 
3099  case 'data':
3100  case 'external':
3101  if (is_array($_SESSION['_last_desktop'])) {
3102  $_site = new Site(
3103  $_SESSION['_last_desktop']['name'],
3104  $_SESSION['_last_desktop']['language']
3105  );
3106  return $_site;
3107  }
3108  return new Site();
3109  }
3110  return $site;
3111  }
3112 
3118  public static function getLatestEgotecVersion() {
3119  require_once('base/Ego_Update.php');
3120  $update = new Ego_Update();
3121  return $update->getLatestEgocmsVersion();
3122  }
3123 
3131  public static function getDiff($diff1, $diff2) {
3132  require_once('diff/Ego_Diff.php');
3133  // Bestimmte Elemente ignorieren
3134  $ignored_elements = array();
3135  foreach (array('script', 'svg') as $element) {
3136  while (preg_match('/<' . $element . '[^>]*>(.*?)<\/' . $element . '>/ims', $diff1, $m)) {
3137  $key = '__EGOTEC__IGNORE__' . md5($m[0]) . '__IGNORE__EGOTEC__';
3138  $ignored_elements[$key] = $m[0];
3139  $diff1 = str_replace($m[0], $key, $diff1);
3140  $diff2 = str_replace($m[0], $key, $diff2);
3141  }
3142  }
3143  $diff = new Ego_Diff();
3144  $result = $diff->compare($diff2, $diff1, false);
3145  // Javascript Code wieder rein schreiben
3146  foreach ($ignored_elements as $key => $code)
3147  {
3148  $result = str_replace($key, $code, $result);
3149  }
3150  return $result;
3151  }
3152 
3161  public static function getExceptionURL($params = array(), $placeholder = false) {
3162  $content = '#';
3163 
3164  if ($placeholder) {
3165  if ($GLOBALS['is_mail']) {
3166  $media = rtrim(Ego_System::getBaseUrl(), '/') . '/bin/media/error.php';
3167  } else {
3168  $media = $GLOBALS['egotec_conf']['url_dir'] . 'bin/media/error.php';
3169  }
3170  } else {
3171  if ($GLOBALS['is_mail']) {
3172  $media = rtrim(Ego_System::getBaseUrl(), '/') . '/pub/missing_file.gif';
3173  } else {
3174  $media = $GLOBALS['egotec_conf']['url_dir'].'pub/missing_file.gif';
3175  }
3176  }
3177 
3178  if ($params['site']) {
3179  try {
3180  $site = new Site($params['site'], $params['lang']);
3181  } catch (Site_Exception $e) {
3182  $site = null;
3183  }
3184 
3185  if ($site) {
3186  if (
3187  $site->site['type'] == 'media'
3188  && ($params['width'] || $params['height'])
3189  ) {
3190  return $media . '?' . http_build_query([
3191  'width' => $params['width'],
3192  'height' => $params['height']
3193  ]);
3194  } else if ($site->site['error_id'] && $errorPage = $site->getPage($site->site['error_id'])) {
3195  return $errorPage->getUrl();
3196  } else {
3197  return $content;
3198  }
3199  }
3200  }
3201 
3202  return $content;
3203  }
3204 
3230  public static function getFallbackFile($type, $name, $path, $skip = array('module'), $url = false, $relative = false, $parent = '') {
3231  $cache = self::getCache();
3232  $cache_key = 'fallbackFiles';
3233  $map_key = md5(json_encode(func_get_args()));
3234 
3235  if (empty(self::$fallbackMapping)) {
3236  self::$fallbackMapping = $cache->get($cache_key) ?? array();
3237  }
3238 
3239  if (isset(self::$fallbackMapping[$map_key])) {
3240  $result = self::$fallbackMapping[$map_key];
3241  } else {
3242  $result = '';
3243 
3244  $path = ltrim($path, '/');
3245  $files = array(
3246  'custom' => array(
3247  'path' => $GLOBALS['egotec_conf'][$type . '_dir'],
3248  'url' => $GLOBALS['egotec_conf']['url_dir'] . $type . '/',
3249  'file' => $name . '/' . $path
3250  ),
3251  'parent_custom' => array(
3252  'path' => $GLOBALS['egotec_conf'][$type . '_dir'],
3253  'url' => $GLOBALS['egotec_conf']['url_dir'] . $type . '/',
3254  'file' => $parent . '/' . $path
3255  ),
3256  'parent_theme' => array(
3257  'path' => $GLOBALS['egotec_conf']['pub_dir'],
3258  'url' => $GLOBALS['egotec_conf']['url_dir'] . 'pub/',
3259  'file' => 'theme/' . $parent . '/' . $type . '/' . $path
3260  ),
3261  'global' => array(
3262  'path' => $GLOBALS['egotec_conf'][$type . '_dir'],
3263  'url' => $GLOBALS['egotec_conf']['url_dir'] . $type . '/',
3264  'file' => '_global/' . $path
3265  ),
3266  'system' => array(
3267  'path' => $GLOBALS['egotec_conf']['lib_dir'],
3268  'url' => $GLOBALS['egotec_conf']['url_dir'] . 'lib/',
3269  'files' => ['type/' . $type . '/' . $path, $path]
3270  ),
3271  'module' => array(
3272  'path' => $GLOBALS['egotec_conf']['bin_dir'],
3273  'url' => $GLOBALS['egotec_conf']['url_dir'] . 'bin/',
3274  'files' => ['type/skin/' . $path, 'page/' . $path]
3275  ),
3276  'custom_system' => array(
3277  'path' => $GLOBALS['egotec_conf']['var_dir'] . 'lib/',
3278  'url' => $GLOBALS['egotec_conf']['url_dir'] . 'var/lib/',
3279  'file' => $path
3280  ),
3281  'custom_module' => array(
3282  'path' => $GLOBALS['egotec_conf']['var_dir'] . 'bin/',
3283  'url' => $GLOBALS['egotec_conf']['url_dir'] . 'var/bin/',
3284  'file' => $path
3285  )
3286  );
3287  if (empty($name)) {
3288  $skip[] = 'custom';
3289  }
3290  if (empty($parent)) {
3291  $skip[] = 'parent_custom';
3292  $skip[] = 'parent_theme';
3293  } elseif ($type != 'skin') {
3294  $skip[] = 'parent_custom';
3295  }
3296  foreach ($files as $key => $file) {
3297  $list = isset($file['files']) ? $file['files'] : [$file['file']];
3298  foreach ($list as $item) {
3299  $path_file = $file['path'] . $item;
3300  $url_file = $file['url'] . $item;
3301  if ($relative) {
3302  $pos = strpos($url_file, $GLOBALS['egotec_conf']['url_dir']);
3303  if ($pos === 0) {
3304  $url_file = substr_replace(
3305  $url_file,
3306  '',
3307  0,
3308  strlen($GLOBALS['egotec_conf']['url_dir'])
3309  );
3310  }
3311  }
3312  if (!in_array($key, $skip) && is_file($path_file)) {
3313  $result = $url ? $url_file : $path_file;
3314  break 2;
3315  }
3316  }
3317  }
3318 
3319  self::$fallbackMapping[$map_key] = $result;
3320  $cache->set($cache_key, self::$fallbackMapping);
3321  }
3322 
3323  return $result;
3324  }
3325 
3341  public static function getFiles($type, $name, $path, $skip = array(), $parent = '', $return_path = false, $get_variants = true) {
3342  $cache = self::getCache();
3343  $cache_key = 'getFiles' . md5(json_encode(func_get_args()));
3344  $result = $cache->get($cache_key);
3345 
3346  if ($result === null) {
3347  $original_path = $path;
3348  $original_skip = $skip;
3349 
3353  $result = new stdClass();
3354  $result->{'_empty'} = $GLOBALS['auth']->translate('Standard');
3355 
3356  $files = array(
3357  'custom' => array(
3358  'path' => $GLOBALS['egotec_conf'][$type . '_dir'],
3359  'file' => $name . '/' . $path
3360  ),
3361  'parent_custom' => array(
3362  'path' => $GLOBALS['egotec_conf'][$type . '_dir'],
3363  'file' => $parent . '/' . $path
3364  ),
3365  'parent_theme' => array(
3366  'path' => $GLOBALS['egotec_conf']['egotec_dir'] . 'pub/',
3367  'file' => 'theme/' . $parent . '/' . $type . '/' . $path
3368  ),
3369  'global' => array(
3370  'path' => $GLOBALS['egotec_conf'][$type . '_dir'],
3371  'file' => '_global/' . $path
3372  ),
3373  'pub' => array(
3374  'path' => $GLOBALS['egotec_conf']['pub_dir'],
3375  'url' => $GLOBALS['egotec_conf']['url_dir'] . 'pub/',
3376  'file' => 'type/' . $type . '/' . $path
3377  ),
3378  'system' => array(
3379  'path' => $GLOBALS['egotec_conf']['lib_dir'],
3380  'file' => 'type/' . $type . '/' . $path
3381  ),
3382  'module' => array(
3383  'path' => $GLOBALS['egotec_conf']['bin_dir'],
3384  'file' => 'type/skin/' . $path
3385  )
3386  );
3387  if (empty($name)) {
3388  $skip[] = 'custom';
3389  }
3390  if (empty($parent)) {
3391  $skip[] = 'parent_custom';
3392  $skip[] = 'parent_theme';
3393  }
3394  foreach ($files as $key => $file) {
3395  if (!in_array($key, $skip)) {
3396  $list = glob($file['path'] . $file['file']);
3397  if (!empty($list)) {
3398  foreach ($list as $match) {
3399  if (@is_file($match)) {
3400  $parts = explode('.', basename($match));
3401  $i = $get_variants ? count($parts) - 2 : 0;
3402  if ($i >= 0 && $parts[$i]) {
3403  $variant = $parts[$i];
3404  if ($return_path) {
3405  $relative_path = substr($match, strlen($GLOBALS['egotec_conf']['egotec_dir']));
3406  $result->{$relative_path} = ucfirst($variant);
3407  } else {
3408  $result->{$variant} = ucfirst($variant);
3409  }
3410  }
3411  }
3412  }
3413  }
3414  }
3415  }
3416  $result = (array) $result;
3417  if (strpos($original_path, '.html') !== false) {
3418  // Bei .html Dateien auch nach .tpl Dateien suchen
3419  $result = array_merge($result, self::getFiles($type, $name, str_replace('.html', '.tpl', $original_path), $original_skip, $parent, $return_path, $get_variants));
3420  }
3421 
3422  $cache->set($cache_key, $result);
3423  }
3424 
3425  return $result;
3426  }
3427 
3441  public static function getVariantFiles($type, $name, $path, $skip = array(), $parent = '') {
3442  $path = substr_replace($path, '.*', strrpos($path, '.'), 0);
3443  return self::getFiles($type, $name, $path, $skip, $parent);
3444  }
3445 
3452  public static function getUrlParams($url = '') {
3453  $params = array();
3454  if (!$url && $_REQUEST['_url']) {
3455  $url = $_REQUEST['_url'];
3456  if ($url[0] == '/') {
3457  $url = substr($url, 1);
3458  }
3459  if ($query_pos = strpos($url, '?')) {
3460  $url = substr($url, 0, $query_pos);
3461  }
3462  $dot_pos = strrpos($url, '.');
3463  if ($dot_pos !== false) {
3464  $url = substr($url, 0, $dot_pos);
3465  }
3466  }
3467  if ($url) {
3468  // Query Parameter
3469  parse_str(parse_url($url, PHP_URL_QUERY), $params);
3470 
3471  if (strpos($url, 'index.php') === false) {
3472  // Rewrite1 Parameter (-key-value)
3473  $url = explode('-', parse_url($url, PHP_URL_PATH));
3474  $value = end($url);
3475  while ($value !== false)
3476  {
3477  $value = preg_replace('/\..*?$/', '', $value);
3478  $key = prev($url);
3479  if ($key === false || strpos($key, '/') !== false)
3480  {
3481  break;
3482  }
3483  $params[$key] = $value;
3484  $key = urldecode($key);
3485  $value = prev($url);
3486  }
3487  $params = array_reverse($params);
3488  }
3489  }
3490  return $params;
3491  }
3492 
3498  public static function getRequest($request = array()) {
3499  if (empty($request)) {
3500  $request = $_REQUEST;
3501  foreach ($_COOKIE as $key => $val) {
3502  unset($request[$key]);
3503  }
3504  }
3505  unset($request['_url']);
3506  unset($request['p']);
3507  unset($request['id']);
3508  unset($request['site']);
3509  unset($request['lang']);
3510  unset($request['skin']);
3511  unset($request['no301']);
3512  unset($request['return_absolute']);
3513  unset($request['return_relative']);
3514  unset($request['return_original']);
3515  unset($request['return_https']);
3516  return $request;
3517  }
3518 
3539  public static function cleanTypes($value) {
3540  if (is_array($value)) {
3541  $new_value = [];
3542  $numeric_keys = true;
3543  $preserved_keys = ['old_phase', 'new_phase'];
3544  foreach ($value as $k => $v) {
3545  if (in_array($k, $preserved_keys, true)) {
3546  // Workflow Status muss immer als String gespeichert werden
3547  $v = (string) $v;
3548  } else {
3549  $v = self::cleanTypes($v);
3550  }
3551  if (
3552  !in_array($k, $preserved_keys, true) // Diese Schlüssel nicht korrigieren
3553  && (
3554  in_array($k, ['', 'undefined'], true)
3555  || (empty($v) && $v !== 0)
3556  )
3557  ) {
3558  continue;
3559  }
3560  $new_value[$k] = $v;
3561  if (!is_numeric($k)) {
3562  $numeric_keys = false;
3563  }
3564  }
3565  if ($numeric_keys) {
3566  // Sicherstellen, dass bei numerischen Schlüsseln immer aufsteigend sortiert ist
3567  ksort($new_value);
3568  }
3569  $value = $new_value;
3570  } elseif (is_string($value)) {
3571  if (preg_match('/^[1-9]+[0-9]*$/', $value)) {
3572  // Nur Ganzzahlen umwandeln; ansonsten können Werte wie 6.350 in 6,35 umgewandelt werden
3573  // Auch nicht für Ganzzahlen, die mit einer 0 beginnen
3574  $value = $value + 0;
3575  } elseif ($value === '0') {
3576  $value = 0;
3577  } elseif (in_array($value, ['true', 'false'], true)) {
3578  $value = $value == 'true';
3579  } elseif (in_array($value, ['null', 'undefined', '_empty'], true)) {
3580  $value = null;
3581  }
3582  }
3583  return $value;
3584  }
3585 
3592  public static function cleanUrl($url) {
3593  if (preg_match('/^([^\/:]+:\/\/)?(.*?)$/', $url, $matches)) {
3594  $protocol = $matches[1];
3595  $uri = $matches[2];
3596  $uri = str_replace('//', '/', $uri);
3597  $url = $protocol.$uri;
3598  }
3599  return $url;
3600  }
3601 
3608  public static function isCurrentUrl($url) {
3609  if (isset($_SERVER['REQUEST_URI'])) {
3610  $data = array(
3611  array('url' => ltrim(preg_replace('#^https?://.*?/#i', '', rawurldecode($_SERVER['REQUEST_URI'])), '/')),
3612  array('url' => ltrim(preg_replace('#^https?://.*?/#i', '', rawurldecode($url)), '/'))
3613  );
3614  if ($data[0]['url'] != $data[1]['url']) {
3615  // Die URLs können trotzdem identisch sein
3616  $data[0]['info'] = self::getUrlInfo($data[0]['url']);
3617  $data[1]['info'] = self::getUrlInfo($data[1]['url']);
3618  unset($data[0]['info']['params']['p'], $data[1]['info']['params']['p']);
3619  if (
3620  $data[0]['info']['suffix'] == $data[1]['info']['suffix']
3621  && sizeof($data[0]['info']['params']) == sizeof($data[1]['info']['params'])
3622  && sizeof($data[0]['info']['parts']) == sizeof($data[1]['info']['parts'])
3623  ) {
3624  // Die Bestandteile stimmen überein, prüfen ob die Parameter identisch sind
3625  foreach ($data[0]['info']['params'] as $key => $value) {
3626  if (str_replace('+',' ',$value) != str_replace('+',' ',$data[1]['info']['params'][$key])) {
3627  return false;
3628  }
3629  }
3630  // Die Parameter stimmen überein, prüfen ob die Namen identisch sind
3631  foreach ($data[0]['info']['parts'] as $key => $value) {
3632  $value = mb_strtoupper($value);
3633  $data[1]['info']['parts'][$key] = mb_strtoupper($data[1]['info']['parts'][$key]);
3634  if (
3635  $value != $data[1]['info']['parts'][$key]
3636  && $value != urldecode($data[1]['info']['parts'][$key])
3637  ) {
3638  return false;
3639  }
3640  }
3641  return true;
3642  }
3643  } else {
3644  return true;
3645  }
3646  }
3647  return false;
3648  }
3649 
3657  public static function getUrlInfo($url, $encode = false) {
3658  $url = str_replace('&amp;', '&', $url);
3659  $info = array(
3660  'suffix' => null,
3661  'params' => self::getUrlParams($url),
3662  'query' => (string) parse_url($url, PHP_URL_QUERY),
3663  'protocol' => ($scheme = parse_url($url, PHP_URL_SCHEME)) ? "$scheme://" : null,
3664  'anchor' => parse_url($url, PHP_URL_FRAGMENT)
3665  );
3666 
3667  // Suffix ermitteln
3668  if (($dot = strrpos($url, '.')) !== false) {
3669  $info['suffix'] = preg_split('/[\/?#]/', substr($url, $dot))[0];
3670  }
3671 
3672  // Mediapool ermitteln
3673  if (preg_match('/\/_\/([^?#]+)/', $url, $match)) {
3674  $info['params']['pool'] = urldecode($match[1]);
3675  }
3676 
3677  // Bestandteile ermitteln
3678  $info['parts'] = array_filter(explode('/', parse_url($url, PHP_URL_PATH)), function($value) {
3679  return $value !== '';
3680  });
3681  $info['parts'] = array_map(function($value) {
3682  if (preg_match('/^(.*?)\./', $value, $match)) {
3683  $value = $match[1];
3684  }
3685  if (substr_count($value, '-') % 2 == 0) {
3686  $value = preg_replace('/^([^-]*).*?$/', '$1', $value);
3687  } else {
3688  $value = preg_replace('/^([^-]*-[^-]*).*?$/', '$1', $value);
3689  }
3690  return $value;
3691  }, $info['parts']);
3692 
3693  // URL wurde unkodiert übergeben
3694  if ($encode) {
3695  $info['parts'] = array_map('self::encode_path', $info['parts']);
3696  }
3697 
3698  return $info;
3699  }
3700 
3707  public static function getFileInfo($file) {
3708  if (self::file_exists($file)) {
3709  $cache = self::getCache();
3710  $cache_key = 'getFileInfo' . md5($file);
3711  $info = $cache->get($cache_key);
3712 
3713  if ($info === null || filemtime($file) > $cache->getLastChanged()) {
3714  $info = array();
3715 
3716  $finfo = new finfo();
3717  $mime_type = $finfo->file($file, FILEINFO_MIME_TYPE);
3718 
3719  $info['size'] = @filesize($file);
3720  $info['mime'] = $mime_type;
3721 
3722  if (stripos($mime_type, 'video/') === 0) {
3723  // Bei Videos die Informationen über ffprobe (ffmpeg) ermitteln
3724  // Dimensionen
3725  self::exec('ffprobe', ['-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=height,width', '-of', 'csv=s=x:p=0', $file], $output);
3726  $s = explode('x', $output[0]);
3727  $info['width'] = (int)$s[0];
3728  $info['height'] = (int)$s[1];
3729 
3730  // Dauer
3731  self::exec('ffprobe', ['-v', 'error', '-show_entries', 'format=duration', '-of', 'default=nw=1:nk=1', $file], $output);
3732  $s = ceil((float) $output[0]);
3733  $info['duration'] = $s
3734  ? sprintf('%02d:%02d:%02d', $s / 3600, $s / 60 % 60, $s % 60)
3735  : '--:--:--';
3736  } elseif (stripos($mime_type, 'image/') === 0) {
3737  // Bei Bildern die Breite und Höhe ermitteln
3738  require_once 'base/Ego_Image.php';
3739  [$info['width'], $info['height']] = Ego_Image::getDimensions($file);
3740  }
3741 
3742  $cache->set($cache_key, $info);
3743  }
3744  return $info;
3745  }
3746  return array();
3747  }
3748 
3754  public static function getVirtualHosts() {
3755  $virtual_hosts = $h = array();
3756 
3757  $file_name = $GLOBALS['egotec_conf']['var_dir'].'conf/virtual_hosts.ini';
3758  if (self::file_exists($file_name)) {
3759  $virtual_hosts = parse_ini_file($file_name,1);
3760  }
3761  foreach($virtual_hosts as $k => $v) {
3762  $h[mb_strtolower($k)] = $v;
3763  }
3764  return $h;
3765  }
3766 
3773  public static function getFormats($type) {
3774  switch ($type) {
3775  case 'image':
3776  return array('jpg', 'jpeg', 'gif', 'png', 'bmp', 'svg', 'ico', 'webp', 'avif');
3777  case 'web':
3778  return array('image/gif', 'image/png', 'image/jpeg', 'image/jpg');
3779  case 'archive':
3780  return array('zip', 'rar', 'tar', 'gz', 'bz2', '7z');
3781  case 'video':
3782  return array('mp4', 'ogg', 'webm');
3783  default:
3784  throw new Exception('Format type does not exist.');
3785  }
3786  }
3787 
3798  public static function sortPages($pages, $sorttype = 'field', $sortby = 'id', $sortdirection = "asc")
3799  {
3800  // Es kann nur mit Arrays sortiert werden
3801  if (gettype($pages) == 'object')
3802  {
3803  $pagesnew = array();
3804  foreach ($pages as $p)
3805  {
3806  $pagesnew[] = $p;
3807  }
3808  $pages = $pagesnew;
3809  }
3810 
3811  if (is_array($pages))
3812  {
3813  usort($pages, function($a, $b) use ($sorttype, $sortby, $sortdirection) {
3814  $r = function($s) {
3815  return str_replace(
3816  array('ä', 'ö', 'ü', 'ß'),
3817  array('ae', 'oe', 'ue', 'ss'),
3818  $s
3819  );
3820  };
3821  $v1 = $r(mb_strtolower(Ego_System::getAssocValue(is_object($a) ? $a->{$sorttype} : $a[$sorttype], $sortby)));
3822  $v2 = $r(mb_strtolower(Ego_System::getAssocValue(is_object($b) ? $b->{$sorttype} : $b[$sorttype], $sortby)));
3823  return $sortdirection == 'asc' ? strnatcmp($v1, $v2) : strnatcmp($v2, $v1);
3824  });
3825  }
3826  else
3827  {
3828  return array();
3829  }
3830  return $pages;
3831  }
3832 
3839  public static function getProtocol($https = false) {
3840  return 'http' . ($https || $_SERVER['HTTPS'] == 'on' || $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'
3841  ? 's' : '') . '://';
3842  }
3843 
3849  public static function getBaseUrl() {
3850  return ($_SERVER['HTTP_HOST']
3851  ? self::getProtocol().$_SERVER['HTTP_HOST']
3852  : rtrim($GLOBALS['egotec_conf']['local_server_access'], '/'))
3853  .$GLOBALS['egotec_conf']['url_dir'];
3854  }
3855 
3862  public static function getDiskUsage($recalc = false) {
3863  $cache_file = $GLOBALS['egotec_conf']['tmp_dir'].'disk_usage';
3864  if (!$recalc && self::file_exists($cache_file)) {
3865  $usage = unserialize(self::file_get_contents($cache_file));
3866  } else {
3867  @set_time_limit(0);
3868  @clearstatcache();
3869  $usage = array(
3870  'elements' => array(
3871  'system' => array(
3872  'all' => array(
3873  'label' => $GLOBALS['auth']->translate('System'),
3874  'color' => '#f8482b',
3875  'dirs' => array(
3876  $GLOBALS['egotec_conf']['lib_dir'],
3877  $GLOBALS['egotec_conf']['bin_dir'],
3878  $GLOBALS['egotec_conf']['egotec_dir'].'pub'.DIRECTORY_SEPARATOR
3879  )
3880  )
3881  ),
3882  'data' => array(
3883  'backup' => array(
3884  'label' => $GLOBALS['auth']->translate('Backups'),
3885  'color' => '#0e88f0',
3886  'dirs' => array(
3887  $GLOBALS['egotec_conf']['backup_dir']
3888  )
3889  ),
3890  'cache' => array(
3891  'label' => $GLOBALS['auth']->translate('Cache'),
3892  'color' => '#2fedac',
3893  'dirs' => array(
3894  $GLOBALS['egotec_conf']['cache_dir'],
3895  $GLOBALS['egotec_conf']['cachemedia_dir']
3896  )
3897  ),
3898  'log' => array(
3899  'label' => $GLOBALS['auth']->translate('Logs'),
3900  'color' => '#edc72f',
3901  'dirs' => array(
3902  $GLOBALS['egotec_conf']['log_dir']
3903  )
3904  ),
3905  'tmp' => array(
3906  'label' => $GLOBALS['auth']->translate('Temporär'),
3907  'color' => '#efd2de',
3908  'dirs' => array(
3909  $GLOBALS['egotec_conf']['tmp_dir']
3910  )
3911  ),
3912  'media' => array(
3913  'label' => $GLOBALS['auth']->translate('Medien'),
3914  'color' => '#4fac0b',
3915  'dirs' => array(
3916  $GLOBALS['egotec_conf']['var_dir'].'media'.DIRECTORY_SEPARATOR
3917  )
3918  )
3919  ),
3920  'customer' => array(
3921  'site' => array(
3922  'label' => $GLOBALS['auth']->translate('Skripte'),
3923  'color' => '#deefd2',
3924  'dirs' => array(
3925  $GLOBALS['egotec_conf']['site_dir']
3926  )
3927  ),
3928  'skin' => array(
3929  'label' => $GLOBALS['auth']->translate('Designs'),
3930  'color' => '#8813f5',
3931  'dirs' => array(
3932  $GLOBALS['egotec_conf']['skin_dir']
3933  )
3934  )
3935  )
3936  ),
3937  'total' => array(),
3938  'used' => array(),
3939  'free' => array(),
3940  'unknown' => array(),
3941  'dirs' => array(),
3942  'date' => time(),
3943  'time' => microtime(true),
3944  'config' => array(
3945  'bytes' => true
3946  )
3947  );
3948  if (empty($GLOBALS['egotec_conf']['skip_disk_usage'])) {
3949  $total = (float) @disk_total_space($GLOBALS['egotec_conf']['egotec_dir']);
3950  } else {
3951  $total = 0;
3952  }
3953  $origin = md5($total);
3954  $usage['total'][$origin] = $total;
3955  $usage['used'][$origin] = 0;
3956  $usage['free'][$origin] = 0;
3957  $usage['unknown'][$origin] = 0;
3958  $usage['dirs'][$origin] = $GLOBALS['egotec_conf']['egotec_dir'];
3959  $total_values = array($usage['total'][$origin]);
3960  foreach ($usage['elements'] as $element => $types) {
3961  foreach ($types as $type => $data) {
3962  foreach ($data['dirs'] as $dir) {
3963  if (!self::file_exists($dir)) {
3964  egotec_warning_log("Path '$dir' doesn't exist.");
3965  continue;
3966  }
3967  if (empty($GLOBALS['egotec_conf']['skip_disk_usage'])) {
3968  $cms_dir = self::getDirectorySize($dir);
3969  $used = (float) $cms_dir['size'];
3970  } else {
3971  $used = 0;
3972  }
3973  $usage['elements'][$element][$type]['value'] += $used;
3974  if (
3975  empty($GLOBALS['egotec_conf']['skip_disk_usage'])
3976  && strpos($dir, $GLOBALS['egotec_conf']['egotec_dir']) !== 0
3977  ) {
3978  $base_dir = substr($dir, 0,
3979  strrpos(rtrim($dir, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR) + 1
3980  );
3981  $total = (float) @disk_total_space($base_dir);
3982  if ($total > 0) {
3983  $skip = false;
3984  foreach ($total_values as $size) {
3985  if ($total == $size) {
3986  $skip = true;
3987  break;
3988  }
3989  }
3990  if (!$skip) {
3991  $origin = md5($total);
3992  $usage['total'][$origin] += $total;
3993  $usage['dirs'][$origin] = $base_dir;
3994  $total_values[] = $total;
3995  }
3996  }
3997  } else {
3998  $origin = md5($total_values[0]);
3999  }
4000  $usage['used'][$origin] += $used;
4001  $usage['elements'][$element][$type]['origin'] = $origin;
4002  }
4003  }
4004  }
4005  foreach ($usage['total'] as $origin => $value) {
4006  $usage['free'][$origin] = $value - $usage['used'][$origin];
4007 
4008  // Unbekannten, genutzten Speicherplatz ermitteln
4009  if (empty($GLOBALS['egotec_conf']['skip_disk_usage'])) {
4010  $free = (float)@disk_free_space($usage['dirs'][$origin]);
4011  } else {
4012  $free = 0;
4013  }
4014  if ($free > 0 && $free < $usage['free'][$origin]) {
4015  $usage['unknown'][$origin] = $usage['free'][$origin] - $free;
4016  $usage['used'][$origin] += $usage['unknown'][$origin];
4017  $usage['free'][$origin] = $free;
4018  } else {
4019  $usage['unknown'][$origin] = 0;
4020  }
4021  }
4022  $usage['time'] = microtime(true) - $usage['time'];
4023  @file_put_contents($cache_file, serialize($usage));
4024  }
4025  return $usage;
4026  }
4027 
4033  public static function getLoadAverage() {
4034  if (!self::isWindows()) {
4035  self::exec('cat', ['/proc/cpuinfo', '|', 'grep processor', '|', 'wc -l'], $output, $return, false);
4036  $cpu = ((int) $output[0]) ?: 1;
4037  $load = sys_getloadavg();
4038  return $load[0] / $cpu;
4039  }
4040  return 0;
4041  }
4042 
4049  public static function getIp($anonymized = false) {
4050  $ip = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : ($_SERVER['REMOTE_ADDR'] ?? '');
4051  if ($anonymized) {
4052  $ip = preg_replace('/\.\d+$/ims', '.0', $ip); // IPv4
4053  $ip = preg_replace('/:.*?$/ims', '::', $ip); // IPv6
4054  }
4055  return $ip;
4056  }
4057 
4064  public static function gzdecode($string) {
4065  if (function_exists('gzdecode')) {
4066  return gzdecode($string);
4067  } else {
4068  $tmp = tempnam($GLOBALS['egotec_conf']['tmp_dir'], 'gzDecode');
4069  @file_put_contents($tmp, $string);
4070  ob_start();
4071  readgzfile($tmp);
4072  $output = ob_get_clean();
4073  @unlink($tmp);
4074  return $output;
4075  }
4076  }
4077 
4089  public static function replaceLinks($content, $search, $replace) {
4090  if (preg_match_all('/index\.php\?[^>"\' ]+/msi', $content, $matches)) {
4091  foreach ($matches[0] as $url) {
4092  $info = self::getUrlInfo($url);
4093  if (!empty($info['params'])) {
4094  $continue = false;
4095  foreach ($search as $param => $value) {
4096  if (
4097  !isset($info['params'][$param])
4098  || $info['params'][$param] != $value
4099  ) {
4100  $continue = true;
4101  } elseif (isset($replace[$param])) {
4102  $info['params'][$param] = $replace[$param];
4103  }
4104  }
4105  if ($continue) {
4106  continue;
4107  } else {
4108  $query = http_build_query($info['params']);
4109  $content = str_replace($url, 'index.php?'.$query, $content);
4110  }
4111  }
4112  }
4113  }
4114  return $content;
4115  }
4116 
4124  public static function base64Encode($s) {
4125  return strtr(base64_encode($s), '+/=', '-_,');
4126  }
4127 
4135  public static function base64Decode($s) {
4136  return base64_decode(strtr($s, '-_,', '+/='));
4137  }
4138 
4145  public static function arrayValuesRecursive($array) {
4146  $result = array();
4147  foreach ($array as $value) {
4148  if (is_array($value)) {
4149  $result = array_merge($result, self::arrayValuesRecursive($value));
4150  } else {
4151  $result[] = $value;
4152  }
4153  }
4154  return array_unique($result);
4155  }
4156 
4165  public static function arrayFlatRecursive($array, $callback = null) {
4166  $result = array();
4167  array_walk_recursive($array, function($a, $k) use (&$result, $callback) {
4168  if (!is_array($result[$k])) {
4169  $result[$k] = array();
4170  }
4171  if (!empty($callback)) {
4172  $a = call_user_func_array($callback, array($a));
4173  }
4174  array_push($result[$k], $a);
4175  $result[$k] = array_values(array_unique($result[$k]));
4176  });
4177  return $result;
4178  }
4179 
4186  public static function isDevMode($ignore = true) {
4187  if ($ignore && !empty($GLOBALS['egotec_conf']['dev_ignore'])) {
4188  return false;
4189  }
4190 
4191  if (self::$devMode === null) {
4192  self::$devMode = ($GLOBALS['egotec_conf']['devserver'] ?? false)
4193  || self::file_exists($GLOBALS['egotec_conf']['egotec_dir'].'.svn')
4194  || self::file_exists($GLOBALS['egotec_conf']['egotec_dir'].'.git');
4195  }
4196  return self::$devMode;
4197  }
4198 
4205  public static function isStatistic($token_auth) {
4206  // Ist das Statistikmodul vorhanden?
4207  return self::checkLicence($GLOBALS['egotec_conf']['lib_dir'].'stats')
4208  && ($GLOBALS['site']->admin['piwik']['auth_url'] || $GLOBALS['egotec_conf']['piwik']['auth_url'])
4209  && $token_auth
4210  && (
4211  !self::isDevMode()
4212  || !empty($GLOBALS['egotec_conf']['dev']['enable_stats'])
4213  );
4214  }
4215 
4223  public static function getAssocValue($a, $k) {
4224  if (($p = strstr($k, '.', true)) !== false) {
4225  if (($j = strstr($p, '{')) !== false) {
4226  // Suche in einem JSON String
4227  $kj = ltrim(str_replace($p, $j, substr($k, 0, strrpos($k, '}'))), '{');
4228  $s = self::getAssocValue($a, str_replace($j, '', $p));
4229  if (is_string($s)) {
4230  $aj = json_decode($s, true);
4231  if (is_array($aj)) {
4232  return self::getAssocValue($aj, $kj);
4233  }
4234  }
4235  return null;
4236  } elseif (is_array($a)) {
4237  // Suche in einem Array
4238  return self::getAssocValue($a[$p], ltrim(strstr($k, '.'), '.'));
4239  }
4240  return null;
4241  }
4242  return $a[$k];
4243  }
4244 
4253  public static function setAssocValue(&$a, $k, $v) {
4254  if (($p = strstr($k, '.', true)) !== false) {
4255  if (($j = strstr($p, '{')) !== false) {
4256  // Setzen in einem JSON String
4257  $kj = ltrim(str_replace($p, $j, substr($k, 0, strrpos($k, '}'))), '{');
4258  $s = self::getAssocValue($a, ($pj = str_replace($j, '', $p)));
4259  if (is_string($s)) {
4260  $aj = json_decode($s, true);
4261  if (is_array($aj)) {
4262  self::setAssocValue($aj, $kj, $v);
4263  self::setAssocValue($a, $pj, json_encode($aj, JSON_UNESCAPED_UNICODE));
4264  return $v;
4265  }
4266  }
4267  return null;
4268  }
4269 
4270  // Setzen in einem Array
4271  return self::setAssocValue($a[$p], ltrim(strstr($k, '.'), '.'), $v);
4272  }
4273  $a[$k] = $v;
4274  return $a[$k];
4275  }
4276 
4285  public static function getAssocValues($a, $k, $o = '') {
4286  if (
4287  ($p = strstr($k, '.', true)) !== false
4288  || (strpos($k, '?') !== false && ($p = $k))
4289  ) {
4290  if (is_array($a)) {
4291  if (
4292  ($j = strstr($p, '{')) !== false
4293  && (($jh = strstr($p, '#')) === false || $jh > $j)
4294  ) {
4295  // Suche in einem JSON String
4296  $kj = ltrim(str_replace($p, $j, substr($k, 0, strrpos($k, '}'))), '{');
4297  $s = self::getAssocValue($a, ($pj = str_replace($j, '', $p)));
4298  if (is_array($s)) {
4299  $aj = $s;
4300  } else {
4301  $aj = json_decode($s, true);
4302  }
4303  if (is_array($aj)) {
4304  $ar = self::getAssocValues($aj, $kj);
4305  if (is_array($ar)) {
4306  $r = [];
4307  foreach ($ar as $rk => $rv) {
4308  $r[$o . $pj . '{' . $rk . '}'] = $rv;
4309  }
4310  if (!empty($r)) {
4311  return $r;
4312  }
4313  }
4314  }
4315  return null;
4316  } elseif (strpos($p, '?') !== false) {
4317  // Wildcard Suche in einem Array
4318  $an = [];
4319  $pattern = preg_replace_callback('/\?(#.*?#)?/', function($m) {
4320  return isset($m[1]) ? trim($m[1], '#') : '.+';
4321  }, $p);
4322  foreach ($a as $kn => $v) {
4323  if (preg_match('#^' . $pattern . '$#i', $kn)) {
4324  if (strpos($kn, '.') !== false) {
4325  if ($a[$kn] !== null) {
4326  $an[$kn] = $a[$kn];
4327  }
4328  } else {
4329  $vn = self::getAssocValues($a, $kn . strstr($k, '.'), $o);
4330  if ($vn !== null) {
4331  foreach ($vn as $k2 => $v2) {
4332  if ($v2 !== null) {
4333  $an[$k2] = $v2;
4334  }
4335  }
4336  }
4337  }
4338  }
4339  }
4340  if (!empty($an)) {
4341  return $an;
4342  }
4343  } else {
4344  // Suche in einem Array
4345  $kn = ltrim(strstr($k, '.'), '.');
4346  $on = substr($k, 0, -mb_strlen($kn));
4347  return self::getAssocValues($a[$p], $kn, $o . $on);
4348  }
4349  }
4350  return null;
4351  } elseif (is_array($a)) {
4352  return [($o . $k) => $a[$k]];
4353  }
4354  return null;
4355  }
4356 
4365  public static function convertAssocArray($array) {
4366  $converted = [];
4367 
4368  foreach ($array as $key => $value) {
4369  if (is_array($value)) {
4370  $converted[$key] = self::convertAssocArray($value);
4371  } elseif (($new_key = str_replace('__', '.', $key)) != $key) {
4372  $keys = explode('.', $new_key);
4373  self::setAssocValue($converted[array_shift($keys)], implode('.', $keys), $value);
4374  } else {
4375  $converted[$key] = $value;
4376  }
4377  }
4378 
4379  return $converted;
4380  }
4381 
4393  public static function getJSON($path, $values = [], $combine = false, $ignore = [], $replace = true, $no_cache = false) {
4394  $cache = self::getCache();
4395  $cache_key = 'getJSON' . md5(json_encode(func_get_args()));
4396  $result = $cache->get($cache_key);
4397 
4398  if ($result === null || $no_cache) {
4399  $file = self::file_get_contents($path);
4400  if (!empty($file) && is_array($values2 = json_decode(trim($file), true))) {
4401  $combined_values = !empty($values)
4402  ? (
4403  $replace
4404  ? array_replace_recursive($values, $values2) // Werte aus $path um $values erweitern und bestehende überschreiben
4405  : array_replace_recursive($values2, $values) // Werte aus $path um $values erweitern und bestehende ignorieren
4406  )
4407  : $values2;
4408  if ($combine) {
4409  $recursive = function($value, $keys = []) use (&$recursive, $combined_values, $values, $ignore) {
4410  if (!empty($keys) && in_array(implode('.', $keys), $ignore)) {
4411  return $value;
4412  } elseif (is_array($value)) {
4413  foreach ($value as $k => $v) {
4414  $value[$k] = $recursive($v, array_merge($keys, [$k]));
4415  }
4416  } elseif (
4417  is_string($value)
4418  && in_array($value[0], ['+', '-'])
4419  ) {
4420  $old_value = Ego_System::getAssocValue($values, implode('.', $keys));
4421  if ($old_value === null) {
4422  $old_value = '';
4423  }
4424  $array_value = explode(',', substr($value, 1));
4425  switch ($value[0]) {
4426  case '+':
4427  $value = implode(',', array_unique(array_merge(explode(',', $old_value), $array_value)));
4428  break;
4429  case '-':
4430  $value = implode(',', array_unique(array_diff(explode(',', $old_value), $array_value)));
4431  }
4432  return trim($value, ',');
4433  }
4434  return $value;
4435  };
4436  $result = $recursive($combined_values);
4437  } else {
4438  $result = $combined_values;
4439  }
4440  } else {
4441  $result = $values;
4442  }
4443 
4444  $cache->set($cache_key, $result);
4445  }
4446 
4447  return $result;
4448  }
4449 
4457  public static function setJSON($path, $values = array()) {
4458  return self::file_put_contents($path, str_replace(" ", "\t", json_encode($values, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)));
4459  }
4460 
4467  public static function getChecksum($value) {
4468  return md5(is_array($value) ? json_encode($value, JSON_FORCE_OBJECT) : $value);
4469  }
4470 
4477  public static function getCache($path = '_system')
4478  {
4479  $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
4480 
4481  if (array_key_exists($path, self::$cache)) {
4482  return self::$cache[$path];
4483  }
4484 
4485  switch ($GLOBALS['egotec_conf']['site_cache_type']) {
4486  case 'apcu':
4487  require_once('base/Ego_Cache_apcu.php');
4488  $cache = new Ego_Cache_apcu($path);
4489  break;
4490  case 'custom':
4491  require_once($GLOBALS['egotec_conf']['var_dir'].'lib/Ego_Cache_custom.php');
4492  $cache = new Ego_Cache_custom($path);
4493  break;
4494  default:
4495  require_once('base/Ego_Cache_file.php');
4496  $cache = new Ego_Cache_file($path);
4497  }
4498  return (self::$cache[$path] = $cache);
4499  }
4500 
4513  public static function setCookie($name, $value, $expires = 0, $path = '/', $cross_domain = true, $secure = false, $httponly = true) {
4514  $domain = '';
4515  if ($cross_domain) {
4516  // Sub-Domain übergreifendes Cookie setzen
4517  if (
4518  isset($GLOBALS['egotec_conf']['auth']['cookie_domains'])
4519  && !empty($GLOBALS['egotec_conf']['auth']['cookie_domains'])
4520  ) {
4521  foreach (explode(',', $GLOBALS['egotec_conf']['auth']['cookie_domains']) as $d) {
4522  if (preg_match('/\.' . preg_quote(ltrim($d, '.'), '/') . '$/i', $_SERVER['HTTP_HOST'])) {
4523  $domain = $d;
4524  break;
4525  }
4526  }
4527  }
4528  }
4529 
4530  setcookie($name, $value, $expires, $path, $domain, $secure, $httponly);
4531  $_COOKIE[$name] = $value;
4532  }
4533 
4545  public static function removeCookie($name, $expires = -1, $path = '/', $cross_domain = true, $secure = false, $httponly = true) {
4546  if (isset($_COOKIE[$name])) {
4547  self::setCookie($name, null, $expires, $path, $cross_domain, $secure, $httponly);
4548  unset($_COOKIE[$name]);
4549  }
4550  }
4551 
4559  public static function isEqual($a, $b) {
4560  return md5(serialize($a)) == md5(serialize($b));
4561  }
4562 
4579  public static function createCSV($path, $data, $delimiter = ',', $enclosure = '"', $escape_char = '\'') {
4580  $fp = fopen($path, 'w');
4581  foreach ($data as $line) {
4582  fputcsv($fp, $line, $delimiter, $enclosure, $escape_char);
4583  }
4584  fclose($fp);
4585  }
4586 
4607  public static function createXML($path, $data, $root = 'root', $version = '1.0', $encoding = 'UTF-8') {
4608  $xml = '<?xml version="' . $version . '" encoding="' . $encoding . '"?>';
4609  $recursive = function($data) use (&$recursive) {
4610  $result = '';
4611  foreach ($data as $key => $value) {
4612  if (is_array($value)) {
4613  $result .= "<{$key}>" . $recursive($value) . "</{$key}>";
4614  } else {
4615  if (is_string($value)) {
4616  $value = "<![CDATA[{$value}]]>";
4617  }
4618  $result .= "<{$key}>{$value}</{$key}>";
4619  }
4620  }
4621  return $result;
4622  };
4623  self::file_put_contents($path, "{$xml}<{$root}>" . $recursive($data) . "</{$root}>");
4624  }
4625 
4636  public static function getContrastColor($color, $dark = '#000000', $light = '#ffffff', int $minDiff = 0) {
4637  $backgroundRGB = self::hexToRGB($color, $color);
4638  $backgroundLuminance = self::getLuminance($backgroundRGB['r'], $backgroundRGB['g'], $backgroundRGB['b']);
4639 
4640  $darkRGB = self::hexToRGB($dark, $color);
4641  $darkLuminance = self::getLuminance($darkRGB['r'], $darkRGB['g'], $darkRGB['b']);
4642 
4643  $lightRGB = self::hexToRGB($light, $color);
4644  $lightLuminance = self::getLuminance($lightRGB['r'], $lightRGB['g'], $lightRGB['b']);
4645 
4646  // Das sind werte zwischen 1 (inklusive) und 21 (inklusive)
4647  $darkRatio = $backgroundLuminance >= $darkLuminance ? (($backgroundLuminance + 0.05) / ($darkLuminance + 0.05)) : (($darkLuminance + 0.05) / ($backgroundLuminance + 0.05));
4648  $lightRatio = $backgroundLuminance >= $lightLuminance ? (($backgroundLuminance + 0.05) / ($lightLuminance + 0.05)) : (($lightLuminance + 0.05) / ($backgroundLuminance + 0.05));
4649 
4650  return (($darkRatio >= $lightRatio) && (empty($minDiff) || $minDiff < abs(round($darkRatio - $lightRatio)))) ? $dark : $light;
4651  }
4652 
4662  private static function getLuminance(int $r, int $g, int $b): float {
4663  $rs = $r / 255;
4664  $gs = $g / 255;
4665  $bs = $b / 255;
4666 
4667  $rFinal = $rs <= 0.03928 ? $rs / 12.92 : pow(($rs + 0.055) / 1.055, 2.4);
4668  $gFinal = $gs <= 0.03928 ? $gs / 12.92 : pow(($gs + 0.055) / 1.055, 2.4);
4669  $bFinal = $bs <= 0.03928 ? $bs / 12.92 : pow(($bs + 0.055) / 1.055, 2.4);
4670 
4671  return 0.2126 * $rFinal + 0.7152 * $gFinal + 0.0722 * $bFinal;
4672  }
4673 
4681  public static function hexToRGB(string $hex, string $background = '#ffffff'): array {
4682  $hex = str_replace('#', '', $hex);
4683 
4684  if (strlen($hex) != 3 && strlen($hex) != 6 && strlen($hex) !== 4 && strlen($hex) !== 8) {
4685  return [];
4686  } elseif (strlen($hex) == 3) {
4687  $hex = str_split($hex);
4688  $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
4689  } elseif (strlen($hex) == 4) {
4690  $hex = str_split($hex);
4691  $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
4692 
4693  return self::getOpaqueColor([
4694  hexdec(substr($hex,0,2)),
4695  hexdec(substr($hex,2,2)),
4696  hexdec(substr($hex,4,2)),
4697  hexdec("$hex[3]$hex[3]") / 255.0
4698  ], self::hexToRGB($background));
4699  } elseif (strlen($hex) == 8) {
4700  return self::getOpaqueColor([
4701  hexdec(substr($hex,0,2)),
4702  hexdec(substr($hex,2,2)),
4703  hexdec(substr($hex,4,2)),
4704  hexdec(substr($hex, 6, 2)) / 255.0
4705  ], self::hexToRGB($background));
4706  }
4707 
4708  return [
4709  'r' => hexdec(substr($hex,0,2)),
4710  'g' => hexdec(substr($hex,2,2)),
4711  'b' => hexdec(substr($hex,4,2)),
4712  ];
4713  }
4714 
4715  public static function getOpaqueColor(array $color, array $background): array {
4716  $foregroundAlpha = floatval($color[3]);
4717 
4718  return [
4719  'r' => round(($color[0] * $foregroundAlpha) + ($background[0] * (1 - $foregroundAlpha))),
4720  'g' => round(($color[1] * $foregroundAlpha) + ($background[1] * (1 - $foregroundAlpha))),
4721  'b' => round(($color[2] * $foregroundAlpha) + ($background[2] * (1 - $foregroundAlpha)))
4722  ];
4723  }
4724 
4732  public static function includeHtml($src, $once = true) {
4733  $html = '';
4734 
4735  if (!$once || !in_array($src, self::$includedHtml)) {
4736  $type = mb_strtolower(ltrim(strrchr($src, '.'), '.'));
4737  switch ($type) {
4738  case 'css':
4739  $html = '<link rel="stylesheet" property="stylesheet" href="' . $src . '" type="text/css">';
4740  break;
4741  case 'js':
4742  $html = '<script src="' . $src . '"></script>';
4743  }
4744  self::$includedHtml[] = $src;
4745  }
4746 
4747  return $html;
4748  }
4749 
4755  public static function isNobody() {
4756  return $_SESSION['auth_id'] === null;
4757  }
4758 
4764  public static function getAdminMail()
4765  {
4766  return $GLOBALS['egotec_conf']['admin_mail'] ? $GLOBALS['egotec_conf']['admin_mail'] : 'support@egotec.com';
4767  }
4768 
4778  public static function checkRequirePath($path) {
4779  if (
4780  !preg_match('#\.php$#', $path) // nur PHP Dateien
4781  ) {
4782  Ego_System::header(400);
4783  exit;
4784  }
4785  return $path;
4786  }
4787 
4791  private static function shell(String $php_command, String $command, Array $params = array(), &$output = null, &$return_var = null, $log = true) {
4792  if (!(
4793  strpos($command, " ") === false // kein Leerzeichen im Kommando
4794  || ($command[0] == '"' && $command[-1] == '"' && strpos(substr($command, 1, -1), '"') === false) // oder korrekt escaped
4795  )) throw new RuntimeException('Please use parameter binding for security reasons!');
4796 
4797  $output = [];
4798  $pipe = false;
4799 
4800  foreach ($params as $value) {
4801  $value = (string) $value;
4802  if ($value[0]=='-') {
4803  $pos = strpos($value, ' ');
4804  $pos2 = strpos($value, '=');
4805  $eq = false;
4806  if ($pos2) {
4807  if ($pos2>$pos) {
4808  $pos = $pos2;
4809  $eq = true;
4810  } elseif ($value[1]=='-' && $pos>$pos2) {
4811  // Bei "--a=b" Parametern
4812  $pos = $pos2;
4813  $eq = true;
4814  }
4815  }
4816  if ($pos) {
4817  $command.= " ".substr($value, 0, $pos).($eq?"=":" ").escapeshellarg(substr($value, $pos+1));
4818  } else {
4819  $command.= " ".$value;
4820  }
4821  } else {
4822  $command.= " ".($pipe || in_array($value, array('|', '<', '<<', '>', '>>', '2>>', '&', '&&', '2>&1', '2>&1 | tee')) ? $value : escapeshellarg($value));
4823  }
4824  if ($value == '|') {
4825  $pipe = true;
4826  } elseif ($pipe) {
4827  $pipe = false;
4828  }
4829  }
4830 
4831  if ($log) {
4832  egotec_warning_log($php_command.' executing '.$command);
4833  }
4834 
4835  switch ($php_command) {
4836  case 'exec':
4837  return exec($command, $output, $return_var);
4838  case 'system':
4839  return system($command, $return_var);
4840  }
4841  }
4842 
4857  public static function exec(String $command, Array $params = array(), &$output = null, &$return_var = null, $log = true) {
4858  return Ego_System::shell('exec', $command, $params, $output, $return_var, $log);
4859  }
4860 
4874  public static function system(String $command, Array $params = array(), &$return_var = null, $log = true) {
4875  $output = [];
4876  return Ego_System::shell('system', $command, $params, $output, $return_var, $log);
4877  }
4878 
4889  public static function scan(string $path, bool $remove = false, bool $recursive = true, ?array &$summary = []): void {
4890  $params = [$path, '-m', '--infected'];
4891  if ($remove) {
4892  $params[] = '--remove';
4893  }
4894  if ($recursive) {
4895  $params[] = '--recursive';
4896  }
4898  $GLOBALS['egotec_conf']['files']['validate_command']
4899  ? $GLOBALS['egotec_conf']['files']['validate_command']
4900  : 'clamdscan',
4901  $params,
4902  $summary,
4903  $return_var
4904  );
4905 
4906  // Ist das Ergebnis nicht 0, wurde entweder etwas gefunden oder es trat ein Fehler auf
4907  if ($return_var !== 0) {
4908  switch ($return_var) {
4909  // Eine infizierte Datei wurde gefunden
4910  case 1:
4911  $message = $GLOBALS['auth']->translate('Die angegebene Ressource ist nicht sicher und wird verweigert.');
4912  break;
4913 
4914  // Ein Fehler ist aufgetreten (z.B. der Pfad ist ungültig oder kann nicht geöffnet werden)
4915  case 2:
4916  $message = $GLOBALS['auth']->translate('Die Überprüfung der angegebenen Ressource ist fehlgeschlagen.');
4917  break;
4918 
4919  // Ein unbekannter Fehler ist aufgetreten
4920  default:
4921  $message = $GLOBALS['auth']->translate('Bei der Überprüfung der Ressource ist ein unerwarteter Fehler aufgetreten.');
4922  }
4923  throw new Exception($message, is_numeric($return_var) ? (int) $return_var : -1);
4924  }
4925  }
4926 
4932  public static function isLocalRequest() {
4933  $ip = self::getIp();
4934  if (in_array(
4935  $ip,
4936  $GLOBALS['egotec_conf']['local_server_ips']
4937  ? explode(',', $GLOBALS['egotec_conf']['local_server_ips'])
4938  : self::getDefaultLocalServerIps()
4939  )) {
4940  return true;
4941  };
4942  if (
4943  isset($GLOBALS['egotec_conf']['local_server_mask']) &&
4944  substr($ip, 0, strlen($GLOBALS['egotec_conf']['local_server_mask'])) == $GLOBALS['egotec_conf']['local_server_mask']
4945  ) {
4946  return true;
4947  }
4948  return false;
4949  }
4950 
4956  public static function getDefaultLocalServerIps() {
4957  return array("127.0.0.1", "localhost", "::1", "0:0:0:0:0:0:0:1", $_SERVER['SERVER_ADDR']);
4958  }
4959 
4967  public static function flatten($array) {
4968  // Speichere den originalen Array zwischen
4969  $original_array = $array;
4970  $recursive = function($array, $keys = []) use (&$recursive, &$original_array) {
4971  foreach ($array as $key => $value) {
4972  if (is_array($value)) {
4973  foreach ($value as $key2 => $value2) {
4974  unset($original_array[$key]);
4975  if (is_array($value2)) {
4976  $recursive($value2, array_merge($keys, [$key], [$key2]));
4977  } else {
4978  $original_array[array_merge($keys, [$key])[0].'['.implode('][', array_slice(array_merge($keys, [$key], [$key2]), 1)).']'] = $value2;
4979  }
4980  }
4981  } elseif (!empty($keys)) {
4982  $original_array[$keys[0].'['.implode('][', array_slice(array_merge($keys, [$key]), 1)).']'] = $value;
4983  }
4984  }
4985  };
4986  $recursive($original_array);
4987  return $original_array;
4988  }
4989 
4995  public static function createUID() {
4996  return implode('', (
4997  array_map(function() {
4998  return dechex(rand(0, 15));
4999  }, array_fill(0, 32, ''))
5000  ));
5001  }
5002 
5011  public static function convert(string $src, string $dest): void {
5012  self::exec(
5013  'ffmpeg', [
5014  '-y',
5015  '-i',
5016  $src,
5017  '-f mp4',
5018  $dest,
5019  '2>&1'
5020  ]);
5021  }
5022 
5032  public static function compressMediapoolVideo(Mediapool $mediapool, string $file, string $name): void {
5033  $origHeight = Ego_System::exec('ffprobe', [
5034  '-v',
5035  'error',
5036  '-select_streams',
5037  'v:0',
5038  '-show_entries',
5039  'stream=height',
5040  '-of',
5041  'csv=s=x:p=0',
5042  $file,
5043  '2>&1'
5044  ]);
5045 
5046  foreach (self::VIDEO_RESOLUTIONS as $height => $scale) {
5047  if ($origHeight >= $height) {
5048  $tmp = tempnam($GLOBALS['egotec_conf']['tmp_dir'], 'video');
5049  $scale = preg_replace('/^\d+:/', '-2:', $scale); // Seitenverhältnis beibehalten
5050 
5051  Ego_System::exec('ffmpeg', [
5052  '-i',
5053  $file,
5054  '-vf',
5055  'scale=' . $scale,
5056  '-f',
5057  'mp4',
5058  '-strict',
5059  '-2',
5060  '-y',
5061  $tmp,
5062  '-hide_banner',
5063  '2>&1'
5064  ]);
5065 
5066  [$origName, $suffix] = explode('.', $name, 2);
5067  $name = "{$origName}_{$height}p.$suffix";
5068 
5069  // Nur einfügen, wenn die originale Datei noch im Mediapool liegt
5070  if ($mediapool->get("$origName.$suffix")) {
5071  $mediapool->put($tmp, $name, '_compress');
5072  unlink($tmp);
5073  } else {
5074  unlink($tmp);
5075  break;
5076  }
5077  }
5078  }
5079  }
5080 }
static getDimensions($file)
Definition: Ego_Image.php:626
static filterNonUtf8($s, $substitute="", $strict=false)
Definition: Ego_System.php:481
static clearPageLocks()
static convertAssocArray($array)
static checkCron0($site)
static urltopage($url, $params=array(), $only_site=false, $error_page=false, $commit_params=false)
static clearCacheAllSites()
Definition: Ego_System.php:383
static getCache($path='_system')
static getUrlParams($url='')
static system(String $command, Array $params=array(), &$return_var=null, $log=true)
const ADMIN_SKIN
Definition: Ego_System.php:28
static truncate($string, $length, $etc='...', $break_words=false, $middle=false)
static exec(String $command, Array $params=array(), &$output=null, &$return_var=null, $log=true)
static addCronLock($cron_variable, $value, $expiry_date=0)
static getDirectorySize($pfad, &$links=array())
static getMimeTypes($ext='')
static file_put_contents($filename, $data, $flags=0, $context=null)
static move($src, $dest)
static encode_path($url, $id=0)
static convert(string $src, string $dest)
static pathinfo($string)
Definition: Ego_System.php:415
static getFormats($type)
static getAssocValue($a, $k)
static getAssocValues($a, $k, $o='')
static getProtocol($https=false)
static parseCsvLine($str, $delimiter=';', $qualifier='"', $qualifierEscape = '\\')
static getLoadAverage()
static setJSON($path, $values=array())
static parseIniFile($file)
static write_ini_file($path, $assoc_array=array())
Definition: Ego_System.php:977
static isLocalRequest()
static getIp($anonymized=false)
static getBaseUrl()
static cleanTypes($value)
static getChecksum($value)
static readCronLock($cron_variable)
static isNobody()
static getFallbackFile($type, $name, $path, $skip=array('module'), $url=false, $relative=false, $parent='')
static $allSites
Definition: Ego_System.php:284
static removeCookie($name, $expires=-1, $path='/', $cross_domain=true, $secure=false, $httponly=true)
static replaceLinks($content, $search, $replace)
static flushHeaders($headers)
Definition: Ego_System.php:919
static filterUnicode($s)
Definition: Ego_System.php:460
static getVariantFiles($type, $name, $path, $skip=array(), $parent='')
static eternalCache($active, $clear=true)
static getDefaultLocalServerIps()
static secureURL($url)
Definition: Ego_System.php:763
static compressMediapoolVideo(Mediapool $mediapool, string $file, string $name)
static deldir($location, $del=true, $without='', $rename=true)
Definition: Ego_System.php:803
static getAdminMail()
static getFileDescriptorUsage()
static createCSV($path, $data, $delimiter=',', $enclosure='"', $escape_char = '\'')
const REGEX_EMAIL
Definition: Ego_System.php:21
static header($header, $replace=true)
static filterData($data)
Definition: Ego_System.php:558
static getVirtualHosts()
const REGEX_EMAIL_OPTIONAL
Definition: Ego_System.php:23
static createXML($path, $data, $root='root', $version='1.0', $encoding='UTF-8')
static setIntranetReferer($page)
static getRequest($request=array())
static base64Encode($s)
static checkLicence($ini_path)
static dateEncode($string)
Definition: Ego_System.php:651
static isEmail($email)
Definition: Ego_System.php:193
static isWindows()
static getAllSkins()
static getCluster($site=null)
static getFileInfo($file)
static sortPages($pages, $sorttype='field', $sortby='id', $sortdirection="asc")
static getOpaqueColor(array $color, array $background)
static includeHtml($src, $once=true)
static isDevMode($ignore=true)
const REGEX_EMAIL_ESCAPED
Definition: Ego_System.php:25
static isStatistic($token_auth)
static clearMediaCache()
Definition: Ego_System.php:355
static isCurrentUrl($url)
static basename($path)
Definition: Ego_System.php:446
static base64Decode($s)
static getFiles($type, $name, $path, $skip=array(), $parent='', $return_path=false, $get_variants=true)
static getDefaultRobots($default='')
Definition: Ego_System.php:203
static arrayFlatRecursive($array, $callback=null)
static $statusCodes
Definition: Ego_System.php:48
static getDiff($diff1, $diff2)
static getUrlInfo($url, $encode=false)
static getAllSites($username='', $perm='', $table=false, $type='')
static arrayValuesRecursive($array)
static checkSSL()
static getContrastColor($color, $dark='#000000', $light='#ffffff', int $minDiff=0)
static hexToRGB(string $hex, string $background='#ffffff')
static file_exists($file)
const MAX_CLUSTER
Definition: Ego_System.php:31
static flatten($array)
static clearNginxCache()
Definition: Ego_System.php:350
static getDesktopSite($site)
static setAssocValue(&$a, $k, $v)
static getExceptionURL($params=array(), $placeholder=false)
static mkdir($dir, $mode=0755, $recursive=true)
Definition: Ego_System.php:669
static isEmptyContent($str)
static getLatestEgotecVersion()
static getFilePath($dir, $file)
static file_get_contents($filename, $utf8=true, $context=null)
const VIDEO_RESOLUTIONS
Definition: Ego_System.php:33
static loadGlobalConfig()
Definition: Ego_System.php:146
static checkRequirements()
static cleanUrl($url)
static decode_path( $url)
static commandExists($cmd)
static getJSON($path, $values=[], $combine=false, $ignore=[], $replace=true, $no_cache=false)
static scan(string $path, bool $remove=false, bool $recursive=true, ?array &$summary=[])
static redirect($location, $header=302, $params=[])
static setCronLock($expiry_date=0, $lock_msg="")
static noCache()
static removeCronLock()
static getDbDriver($db=null)
static flush($string='')
Definition: Ego_System.php:934
static checkRequirePath($path)
static stringEncode($string, $from='UTF-8', $to='UTF-8')
Definition: Ego_System.php:615
static escape($string, $esc_type='html', $char_set='UTF-8')
Definition: Ego_System.php:218
static copy($src, $dest, $except='', $useLinks=false, $noArchive=false, $preserveDate=false)
static checkEncoding($from='CP1252', $to='UTF-8', $original, $converted)
Definition: Ego_System.php:587
static gzdecode($string)
static $fileList
Definition: Ego_System.php:40
static getSkins($more_themes=array())
static endless($string='', $flush=true)
Definition: Ego_System.php:958
static filesize($file)
static createUID()
static isEqual($a, $b)
static byte_format($byte)
static clearTypeCache($site_name='')
Definition: Ego_System.php:292
static clearCache()
Definition: Ego_System.php:318
static setCookie($name, $value, $expires=0, $path='/', $cross_domain=true, $secure=false, $httponly=true)
static getDiskUsage($recalc=false)
static cronLockExists()
static log($file, $message)
static parseUrl($url)
Definition: Ego_System.php:719
get($name, $dir='', $params=array(), $decoded=false, $block='')
Definition: Mediapool.php:259
put($source, $name, $dir='', $extract=false, $replace=true, $types='', $save=true, $original=true, $source_extra=array(), &$files=array())
Definition: Mediapool.php:46
static createIdentity($params)
Definition: Page.php:11947
static byIdentity($identity, $param=array(), $site=null)
Definition: Page.php:11960
const SITE_DOESNT_EXIST
Definition: Site.php:12
const LANG_DOESNT_EXIST
Definition: Site.php:13
Definition: Site.php:30